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).
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
.