Reputation: 397
Is this code Standard-Compliant?
class Example {
public:
static int x;
};
decltype(auto) Example::x = 1;
int main(){ return 0; }
Clang 3.9.1 compiles it successfully, but gcc 6.3.0 fails: error: conflicting declaration 'decltype(auto) Example::x'
C++14 Standard (ISO/IEC 14882:2014), Section 7.1.6.4, Paragraph 5 (emphasis mine):
A placeholder type 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).
The (re)declaration is not strictly within the member-specification of a class definition, but I don't see any good reason to forbid it. Furthermore, it can be seen also as a (re)declaration of a variable (static data member variable) in namespace scope, which is allowed in Paragraph 4:
The type of a variable declared using auto or decltype(auto) is deduced from its initializer. This use is allowed when declaring variables in a block (6.3), in namespace scope (3.3.6), and in a for-init-statement (6.5.3).
There is a similar C++11 post: Why doesn't the C++11 'auto' keyword work for static members? However, there is only one answer, and then a debate starts in the comments. Besides, clang is usually more reliable in this cases, and according to that answer clang would be wrong and gcc would be correct.
Upvotes: 3
Views: 410
Reputation: 11
It seems gcc becomes confused since it tries to infer the type of x
from the rvalue in its initialization and NOT its declaration in the Example
class. This can result in an inconsistency between the two types, making it look like you are defining a new variable with the same name.
If I understood correctly, the behavior that you are looking for can be implemented with standard-compliant code by using a macro which explicitly infers the type from the variable declaration:
#define auto_typed_init(a) decltype(a) a
(...)
auto_typed_init(Example::x) = 2;
I don't understand, however, why the standard favors the initializer in this case, as is explained in this answer: Why doesn't the C++11 'auto' keyword work for static members?
Upvotes: 1