Search code examples
c++c++11auto

Why there is a limitation that c++ 'auto' cannot stand for multiple types


I mean, why the following example is not a valid construction:

if (auto x = 2, y = "ab"; x != 0) {
  // ...
}

(In my real use case there are calls to some functions instead of 2 and "ab" literals.)

or

std::vector<int> cont1;
std::vector<char> cont2;
for (auto it1 = cont1.begin(), it2 = cont2.begin(); it1 != cont1.end() && it2 != cont2.end(); ++it1, ++it2) {
  // ...
}

It seems that e.g. in the first example, Visual C++ deduces int for auto from the first 2 and then it reports: "ab" cannot initialize int.

But on the other side it is allowed to write:

if (auto [x, y] = std::make_pair(2, "ab"); x != 0) {
  // ...
}

So here, auto stands for different types.

Beside the answer "why", I'd like to know if there are any other workarounds (except the one I have above).


Solution

  • So here, auto stands for different types.

    I wouldn't interpret it that way.

    The auto stands for std::pair<int, char const*>. However, the special thing here is that the name of the pair is [a, b], where a and b refer to the inner members of the pair. I would really like if the language would allow typing the type of the pair explicitly.

    In fact, a and b are not variables. They are structured bindings, and they behave a bit differently. Although that difference is getting less apparent in C++20.

    So really, the auto here is only one type.

    Another way to demonstrate my point is this:

    int x = 0, y = 0;
    auto [a, b] = std::tie(x, y);
    

    Even though it was auto and not auto&, a and b are references to x and y. And attempting to use auto& won't work since the result of std::tie is a prvalue.


    However, there are places where only one auto might refer to different things.

    Consider this:

    auto lambda = [](auto... args) { /* ... */ };
    

    Here, auto... is many different things, but auto... is different than auto.