示例:在头文件中:
class Foo
{
static const int IntArray[];
};
Run Code Online (Sandbox Code Playgroud)
在源文件中:
constexpr int Foo::IntArray[] = { 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)
这在g ++上编译,允许我将初始化列表放在源文件中而不是标题中.(如果它是头文件中的constexpr,则编译器需要在头文件中立即初始化).虽然仍允许在constexpr评估中使用该数组......
这是有效的,可移植的C++吗?
在我们开始语言律师之前,正确的方法是反过来做。在头文件中:
class Foo
{
static constexpr int IntArray[] = { 1, 2, 3, 4 };
};
Run Code Online (Sandbox Code Playgroud)
然后在源文件中:
constexpr int Foo::IntArray[];
Run Code Online (Sandbox Code Playgroud)
如果您static constexpr在类定义中声明了一个类数据成员,则必须立即对其进行初始化。这对于static const数据成员是可选的。如果你static constexpr在程序的任何地方使用数据成员,你必须给出一个与上面类似的定义,在一个源文件中,没有初始化程序。
问题中的示例代码风格不好,显然至少有一个编译器拒绝它,但它实际上似乎符合 C++14 草案标准。[ dcl/constexpr ] 说:
的
constexpr说明符将只应用于一个变量或变量模板,功能或功能模板的声明或声明的定义static文字类型的数据成员。如果函数、函数模板或变量模板的任何声明具有constexpr说明符,则其所有声明都应包含该constexpr说明符。
请注意,由于省略,其声明并非都需要包含说明constexpr符。
稍后在同一部分:
constexpr对象声明中使用的说明符将对象声明为const。这样的对象应具有文字类型并应进行初始化。[...]
但另请参见 [ class.static.data ]:
如果一个非
volatileconststatic数据成员是整型或枚举类型,它在类定义中的声明可以指定一个大括号或等号初始值设定项,其中每个作为赋值表达式的初始值设定项子句都是一个常量表达式。甲文字类型的数据成员可以在类定义与声明说明符; 如果是这样,它的声明应指定一个大括号或等号初始化器,其中每个初始化器子句都是一个赋值表达式staticconstexpr是一个常量表达式。[注意:在这两种情况下,成员可能会出现在常量表达式中。— end note ] 如果该成员在程序中被 odr 使用,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含初始化程序。
在这种情况下,“odr-used”中的 odr 代表单一定义规则,意思是“其名称作为潜在评估表达式出现”。([basic.def.odr]) 最后一句的意思是,如果你static constexpr int foo = 0;在类定义中声明,并且你以后会在表达式中使用它,比如int x = MyClass::foo;,那么一个且只有一个源文件需要有这样一行constexpr int MyClass::foo;在里面,所以链接器知道把它放在哪个目标文件中。
| 归档时间: |
|
| 查看次数: |
1156 次 |
| 最近记录: |