以下代码是否在C ++中定义良好? (*)
我很难弄清楚在标准中的哪个位置,并且搜索网络并没有发现任何具体内容。
struct S;
struct T {
constexpr T() = default;
bool S::* a = nullptr;
int b = 42;
};
const T t{};
// Test. Compiled using: cl /W4 /WX /FAs filename.cpp
#include <stdlib.h>
int main() {
if (t.b != 42) abort();
}
我问的原因是因为它适用于(或似乎)较新版本的GCC和Clang(x86 / x86_64),但使用Visual Studio 2015 Update 2和Update 3 RC失败(**)。
在报告错误之前,我想确定我不是依赖于未定义的行为,或者只是没有搜索正确的术语。
我也尝试使用this post中提到的/vmg
和/vmb
。
(*):我主要关心的是C ++ 14及更高版本,但我认为答案不应适用于C ++ 11。
(**):如果代码定义明确,它看起来像一个codegen bug,它不是指针的分配空间。将struct S
更改为struct S{}
似乎可以使代码“正常工作”。
答案 0 :(得分:5)
您的代码定义明确:
N4594 3.2 / 5
[...] 如果:
,则必须填写班级类型T.
- (5.1) 类型为T的对象定义为(3.1)或
- (5.2) 声明类型为T的非静态类数据成员(9.2)或
- (5.3) T在new-expression(5.3.4)或
中用作对象类型或数组元素类型- (5.4) 左值到右值的转换应用于引用类型为T(4.1)的对象的glvalue,或
- (5.5) 表达式(隐式或显式)转换为类型T(第4,5.2.3,5.2.7,5.2.9,5.4)或
- (5.6) 表达式不是空指针常量,并且具有cv void *以外的类型,将转换为 使用标准转换(第4条),dynamic_cast(5.2.7)或a来键入指向T或T的引用 static_cast(5.2.9)或
- (5.7) 类成员访问运算符应用于类型为T(5.2.5)或
的表达式- (5.8) typeid运算符(5.2.8)或sizeof运算符(5.3.3)应用于类型T的操作数,或
- (5.9) 类型为T的返回类型或参数类型的函数定义为(3.1)或调用(5.2.2)或
- (5.10) 定义了类型为T的基类(第10条)或
- (5.11) 类型T的左值被分配给(5.18)或
- (5.12) 类型T是alignof表达式(5.3.6)或
的主题- (5.13) 异常声明具有类型T,对T的引用或指向T(15.3)的指针。
他们都没有说T
需要完成才能宣布{em>指向T
的成员。