The rule for prohibiting non-static members is in 7.1.6.4 clause 4:
The auto type-specifier can also be used in declaring a variable in
the condition of a selection statement (6.4) or an iteration statement
(6.5), in the type-specifier-seq in the new-type-id or type-id of a
new-expression (5.3.4), in a for-range-declaration, and in declaring a
static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).
I found the rationale for it being static here which reflects how James McNellis explains it in the comment.
One national body dislikes allowing the auto type-specifier for
non-statics. From an e-mail to the authors:
template< class T >
struct MyType : T {
auto data = func();
static const size_t erm = sizeof(data);
};
In order to determine the layout of X, we now have 2-phase name lookup and ADL. Note that func could be either a type or a function;
it may be found in T, the namespace of MyType, the associated
namespace(s) of T when instantiated, the global namespace, an
anonymous namespace, or any namespaces subject to a using directive.
With care we could probably throw some concept_map lookup in for luck.
Depending on the order of header inclusion I might even get different results for ADL, and break the One Definition Rule - which
is not required to be diagnosed.
Because of this controversy, the authors no longer propose that auto
be allowed for non-static data members.
So, basically depending on the order of header inclusion, the type of data
could be very different. Of course, auto x = 5;
would not need to depend on 2-phase name lookup or ADL, however, I'm a assuming that they made it a "blanket" rule because otherwise, they would have to make individual rules for every use case which would make things very complicated.
In the same paper, the author proposes eliminating this restriction, however, it seems this proposal has been rejected probably due to the above rationale and also so that expected behavior can be the same no matter what the initializer is.
auto
uses in C++11 §7.1.6.4). Off the top of my head, I can't think of a good reason why it is prohibited, though I would definitely consider this to be an abuse ofauto
. – Quasarauto
? What is the difference between having a variable with a long/complicated type name (so that it is desirable to useauto
rather than write out its type) at class scope vs. having one at local scope? – Ralphralstonauto x = f(a, b, c);
: I'd have to go find all of thef()
functions and perform overload resolution in my head to figure out the type ofx
. At least at local scope I can look to see what is being done withx
and try to deduce from that what its type is.auto
is insanely useful, but it shouldn't be used everywhere. – Quasarauto
is allowed at namespace scope. I don't see why class scope is singled out like that... – Ralphralstonx
is initialized with anint
literal. – Unchristianauto
with arbitrary initializers at class or namespace scope. I think a lot of people are going way too far with use ofauto
. It's very useful, but not for everything. In my code base, I use it for loop iterators, unutterable types, and very occasionally for local variables. Type names are very useful for improving the comprehensibility of code in many circumstances. – Quasarvar
this,var
that, andvar ugly = SomeFunc<SomeType>(someArg).DoIt().OneMoreTime()
. – Unchristianauto
in a class is used in The C++ Programming Language, Fourth Edition which covers C++11. Mildly annoying that it is not actually C++11. (Found while copying an example on page 1182). – Curtiscurtiss