sizeof in static const member initialization

落花浮王杯 提交于 2019-12-02 08:08:37

问题


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?


回答1:


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).




回答2:


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)



回答3:


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.




回答4:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!