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,
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)
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).
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.
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.
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.
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.
Here I check lots of compilers: https://godbolt.org/ This is one method, but you must evade this kind of hacks in the future.
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;
}