The 2011 C++ standard introduced the new keyword auto
, which can be used for defining variables instead of a type, i.e.
auto p=make_pair(1,2.5); // pair<int,double>
auto i=std::begin(c), end=std::end(c); // decltype(std::begin(c))
In the second line, i
and end
are of the same type, referred to as auto
. The standard does not allow
auto i=std::begin(container), e=std::end(container), x=*i;
when x
would be of different type. My question: why does the standard not allow this last line? It could be allowed by interpreting auto
not as representing some to-be-decuded type, but as indicating that the type of any variable declared auto
shall be deduced from its assigned value. Is there any good reason for the C++11 standard to not follow this approach?
There is actually a use case for this, namely in the initialisation statement of for
loops:
for(auto i=std::begin(c), end=std::end(c), x=*i; i!=end; ++i, x+=*i)
{ ... }
when the scope of the variables i
, end
, and x
is limited to the for
loop. AFAIK, this cannot be achieved in C++ unless those variables have a common type. Is this correct? (ugly tricks of putting all types inside a struct
excluded)
There may also be use cases in some variadic template applications.
If to refer to the C++ 2014 Working Draft then the Standard allows such code.Here is an example from the Standard Draft
I would like to append that in your example auto can not be dedused because iterator type and the value type of the iterator are two different types.
I think it's just a matter of consistency with non-
auto
declarations.This:
is equivalent to:
where the types
int
andint*
are derived from the initializers. In both cases, even thoughint
andint*
are different types, they're permitted to be in the same declaration because of their close syntactic relation. (By the "declaration follows use" rule that C and C++ declarations almost follow, you're defining bothn
and*p
as being of typeint
.)It would have been possible to permit unrelated types in the same declaration:
but the above would have to be equivalent to two separate declarations:
I think the idea when adding
auto
was to make a minimal change to the language, permitting the type to be inferred from an initializer but not changing the kinds of declarations that are possible.Even without
auto
, you could define anint
and anint*
in afor
loop header:but you couldn't declare an
int
and adouble
together. The addition ofauto
simply didn't change that.Outside the context of a
for
loop, it's generally much better to use separate declarations anyway. Shoving a lot of different declarations into afor
loop is arguably a bad idea in most cases. And for the (probably rare) cases where you want a lot of declarations, you can just put them above the loop, something like this:adding another set of
{
}
around the whole thing if you want to limit the scope. (In this case, you'd probably wantend
to beconst
anyway.)According to the final revision of the accepted proposal for this feature, N1737,a possible multi-declarator
auto
implementation is as follows: (from Section 6)As shown by this possible implementation, changing the type would be invalid, and as such would cause an error.
This feature was implemented this way because otherwise it would be different than other types of multi-variable declarations.
I remember seeing a discussion about whether or not to allow changing types, but I cannot remember where. IIRC, they decided that it would be harder to implement, but another reason could be that it was dropped because they could not come to a consensus on when to choose different types (the new behavior) or when to implicitly convert to the deduced type of the first declared variable (the old behavior).