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++ 标准是怎么说的?
你有什么?
您定义了一个名为 A
的 class
。
您的 class 有一个 一个名为 a
.
的 unsigned long
您的 class 有一个 一个名为 b
.
的 static const unsigned long
在某些 C++ 编译器中,class
的 static 和 non-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 visual-studio-2005. Namely because it wasn't supported until c++11.
只要 visual-studio-2013 it's not fully c++11 合规。但我已经验证此代码可以解决此缺陷:
static const unsigned long b = sizeof(decltype(a))
如果您也想要与 visual-studio-2005 一起使用的东西,请考虑将 b
设为全局,而不是 A
:
的静态成员
const unsigned long b = sizeof(A().a)
static
const
-限定成员 in-class 使用非 static
成员的初始化器在 C++11 之前不是 C++ 标准的一部分。
最早完全支持C++11的MSVC编译器是MSVC2017。
该编译器将正确编译您的代码。
我有这样的代码:
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++ 标准是怎么说的?
你有什么?
您定义了一个名为 A
的 class
。
您的 class 有一个 一个名为 a
.
unsigned long
您的 class 有一个 一个名为 b
.
static const unsigned long
在某些 C++ 编译器中,class
的 static 和 non-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).
只要 visual-studio-2013 it's not fully c++11 合规。但我已经验证此代码可以解决此缺陷:
static const unsigned long b = sizeof(decltype(a))
如果您也想要与 visual-studio-2005 一起使用的东西,请考虑将 b
设为全局,而不是 A
:
const unsigned long b = sizeof(A().a)
static
const
-限定成员 in-class 使用非 static
成员的初始化器在 C++11 之前不是 C++ 标准的一部分。
最早完全支持C++11的MSVC编译器是MSVC2017。
该编译器将正确编译您的代码。