简体   繁体   English

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

[英]Pointer to data member of incomplete type

Is the following code well-defined in C++? 以下代码是否在C ++中定义良好? (*) (*)

I'm having a hard time figuring out where to even look in the standard, and searching the web hasn't turned up anything concrete. 我很难弄清楚在标准中的哪个位置,并且搜索网络并没有发现具体的东西。

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();
}

The reason I'm asking is because it works (or seems to) with newer versions of GCC and Clang (x86/x86_64), but fails(**) with Visual Studio 2015 Update 2 and Update 3 RC. 我问的原因是因为它适用于(或似乎)较新版本的GCC和Clang(x86 / x86_64),但在Visual Studio 2015 Update 2和Update 3 RC中失败(**)。

Before reporting a bug I'd like to be sure I'm not relying on undefined behavior or just not searching for the right terms. 在报告错误之前,我想确定我不是依赖于未定义的行为,或者只是没有搜索正确的术语。

I've also tried using /vmg and /vmb as mentioned in this post . 我已经使用还试图/vmg/vmb中提到的这篇文章

(*): I mostly care about C++14 and later, but I don't see any reason the answer shouldn't apply to C++11. (*):我主要关心C ++ 14及更高版本,但我认为答案不适用于C ++ 11。
(**): If the code is well-defined it looks like a codegen bug where it isn't allocation room for the pointer. (**):如果代码定义明确,它看起来像一个codegen bug,它不是指针的分配空间。 Changing struct S to struct S{} seems to make the code "work". struct S更改为struct S{}似乎使代码“工作”。

Your code is well-defined: 您的代码定义明确:

N4594 3.2/5 N4594 3.2 / 5

[...] A class type T must be complete if : [...] 如果符合以下条件,则类T必须完整

  • (5.1) an object of type T is defined (3.1), or (5.1)定义类型为T的对象(3.1),或
  • (5.2) a non-static class data member of type T is declared (9.2), or (5.2)声明类型为T的非静态类数据成员(9.2),或
  • (5.3) T is used as the object type or array element type in a new-expression (5.3.4), or (5.3)T用作new-expression(5.3.4)中的对象类型或数组元素类型,或
  • (5.4) an lvalue-to-rvalue conversion is applied to a glvalue referring to an object of type T (4.1), or (5.4)对参考类型为T(4.1)的对象的glvalue应用左值到右值的转换,或者
  • (5.5) an expression is converted (either implicitly or explicitly) to type T (Clause 4, 5.2.3, 5.2.7, 5.2.9, 5.4), or (5.5)将表达式(隐式或显式)转换为T类(第4,5.2.3,5.2.7,5.2.9,5.4条),或者
  • (5.6) an expression that is not a null pointer constant, and has type other than cv void*, is converted to the type pointer to T or reference to T using a standard conversion (Clause 4), a dynamic_cast (5.2.7) or a static_cast (5.2.9), or (5.6)表达式不是空指针常量,并且具有cv void *以外的类型,使用标准转换(第4节)转换为T的类型指针或引用T(动态广播(5.2.7))或者static_cast(5.2.9),或者
  • (5.7) a class member access operator is applied to an expression of type T (5.2.5), or (5.7)类成员访问运算符应用于类型为T(5.2.5)的表达式,或
  • (5.8) the typeid operator (5.2.8) or the sizeof operator (5.3.3) is applied to an operand of type T, or (5.8)将typeid运算符(5.2.8)或sizeof运算符(5.3.3)应用于类型T的操作数,或者
  • (5.9) a function with a return type or argument type of type T is defined (3.1) or called (5.2.2), or (5.9)具有类型T的返回类型或参数类型的函数定义为(3.1)或调用(5.2.2),或
  • (5.10) a class with a base class of type T is defined (Clause 10), or (5.10)定义了类型为T的基类(第10条),或
  • (5.11) an lvalue of type T is assigned to (5.18), or (5.11)将类型T的左值分配给(5.18),或
  • (5.12) the type T is the subject of an alignof expression (5.3.6), or (5.12)类型T是对齐表达式(5.3.6)的主语,或
  • (5.13) an exception-declaration has type T, reference to T, or pointer to T (15.3). (5.13)异常声明具有类型T,对T的引用或对T的指针(15.3)。

None of them says that T needs to be complete in order to declare pointer-to-member of T . 他们都没有说T需要完整才能声明指向 T 的成员

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM