static const 成员初始化中的 sizeof

sizeof in static const member initialization

我有这样的代码:

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++
};

我在 VC++ 中遇到编译器错误,而在 IAR 中没有错误。 哪个编译器是正确的,C++ 标准是怎么说的?

你有什么?

您定义了一个名为 Aclass

您的 class 有一个 一个名为 a.

unsigned long

您的 class 有一个 一个名为 b.

static const unsigned long

在某些 C++ 编译器中,classstaticnon-static 成员不能混合,特别是在定义阶段。

你想要什么?

static const unsigned long b = sizeof(unsigned long);

这不是您想要的,但这是聪明的编译器试图弄清楚的方式。

为什么???

因为静态成员不会将它们的范围限制在对象定义中。它们超越了对象范围,可以从任何地方访问,例如,只需在控制台中使用 std::cout << A::b << std::endl 输出 A::b

Clang 不接受这种构造,GCC 接受(两者都带有 -g -std=c++98

MSVC 19.14 (visual studio 15.7) 也不接受它,但是 visual studio 15.8 和 MSVC 19.15 接受。

慎重选择。

我在哪里检查所有这些东西?

这里我检查了很多编译器:https://godbolt.org/ 这是一种方法,但你以后一定要避免这种黑客行为。

魔码查错

怪罪的部分是混合C和C++。它仅适用于不带任何检查的旧版本编译:

#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;
}

您的 MSVS 版本很旧,因此基于此,并假设它们默认为 C++03,它们拒绝您的代码是正确的。我将引用 n1905,这对我们的目的来说非常接近 C++03 标准。

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

specifies why this didn't work on . Namely because it wasn't supported until .

只要 it's not fully 合规。但我已经验证此代码可以解决此缺陷:

static const unsigned long b = sizeof(decltype(a))

如果您也想要与 一起使用的东西,请考虑将 b 设为全局,而不是 A:

的静态成员
const unsigned long b = sizeof(A().a)

static const-限定成员 in-class 使用非 static 成员的初始化器在 C++11 之前不是 C++ 标准的一部分。

最早完全支持C++11的MSVC编译器是MSVC2017。

该编译器将正确编译您的代码。