I have such code:
class A
{
public:
unsigned long a;
static const unsigned long b = sizeof(a); // "error C2327: 'A::a' : is not a type name, static, or enumerator" in VC++
};
I got compiler error in VC++ and no errors in IAR. Which compiler is right, what C++ standart says about it?
Your MSVS versions are quite old, so based on that, and assuming they default to C++03, they are correct to reject your code. I'll quote n1905, which for our purposes is pretty close to the C++03 standard.
9.4 [class.static] (emphasis mine)
If an unqualified-id (5.1) is used in the definition of a static member following the member’s declarator-id, and name lookup (3.4.1) finds that the unqualified-id refers to a static member, enumerator, or nested type of the member’s class (or of a base class of the member’s class), the unqualified-id is transformed into a qualified-id expression in which the nested-name-specifier names the class scope from which the member is referenced. The definition of a static member shall not use directly the names of the non-static members of its class or of a base class of its class (including as operands of the sizeof operator). The definition of a static member may only refer to these members to form pointer to members (5.3.1) or with the class member access syntax (5.2.5).
StoryTeller's answer specifies why this didn't work on visual-studio-2005. Namely because it wasn't supported until c++11.
As far as visual-studio-2013 it's not fully c++11 compliant. But I've validated that this code works around the deficiency:
static const unsigned long b = sizeof(decltype(a))
If you want something that will work with visual-studio-2005 as well, consider making b
a global, instead of a static member of A
:
const unsigned long b = sizeof(A().a)
static
const
-qualified member in-class initialisers using non-static
members were not part of the C++ standard until C++11.
The earliest MSVC compiler that fully supports C++11 is MSVC2017.
That compiler will compile your code correctly.
What do you have?
You have the definition of a class
named A
.
Your class has a unsigned long
named a
.
Your class has a static const unsigned long
named b
.
In certain C++ compilers, static and non-static members of a class
can't be mixed, specially in the definition stage.
What do you want?
static const unsigned long b = sizeof(unsigned long);
This is not exactly what you want, but this is how a smart compiler try to figure out.
WHY???
Because static members doesn't limit their scope to the object definition. They overpass the object scope and can be accessed from everywhere simply outputting A::b
in the console using std::cout << A::b << std::endl
, for example.
Clang doesn't accept this construction, GCC does (both with -g -std=c++98
)
MSVC 19.14 (visual studio 15.7) doesn't accept it, too, but visual studio 15.8, with MSVC 19.15, does.
Choose carefully.
Where I check all this stuff?
Here I check lots of compilers: https://godbolt.org/ This is one method, but you must evade this kind of hacks in the future.
Magic code to check and blame
The blame part is for mixing C and C++. It's only for compile with older versions without any checks:
#include <stdio.h>
class A
{
public:
unsigned long a;
static const unsigned long b = sizeof(a); // "error C2327: 'A::a' : is not a type name, static, or enumerator" in VC++
};
int main (void)
{
printf ( "Hello World" ); // I strongly not recommend using printf's in C++ code.
printf ( "%d", A::b ); // This is only to fill a functional example, not a rightful one.
return 0;
}
来源:https://stackoverflow.com/questions/53520397/sizeof-in-static-const-member-initialization