指向不完整类型的数据成员的指针

时间:2016-06-23 19:00:21

标签: c++ c++11 visual-c++

以下代码是否在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{}似乎可以使代码“正常工作”。

1 个答案:

答案 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的成员。