Pointer to an incomplete data item type

Is the following code correct in C ++? (*)

I find it difficult to determine where to even look in the standard, and a search on the Internet did not find anything specific.

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 (tb != 42) abort(); } 

The reason I ask is because it works (or seems to be) with newer versions of GCC and Clang (x86 / x86_64), but with an error (**) with Visual Studio 2015 Update 2 and Update 3 RC .

Before reporting an error, I would like to make sure that I am not relying on undefined behavior or just not looking for the right conditions.

I also tried using /vmg and /vmb as indicated in this post .

(*): I mainly care about C ++ 14 and later, but I see no reason why the answer should not apply to C ++ 11.
(**): If the code is clearly defined, it looks like an error in the codec, where it is not the location of the pointer. Changing struct S to struct S{} seems like the code is "working."

+7
c ++ c ++ 11 visual-c ++
source share
1 answer

Your code is clearly defined:

N4594 3.2 / 5

[...] A class type T must be complete if :

  • (5.1) an object of type T is defined by (3.1) or
  • (5.2) a member of a non-static data type class T is declared (9.2) or
  • (5.3) T is used as the type of an object or the type of an array element in the new expression (5.3.4) or
  • (5.4) the lvalue-to-rvalue transformation is applied to a glvalue related to an object of type T (4.1), or
  • (5.5) the expression (either implicitly or explicitly) is converted to type T (clause 4, 5.2.3, 5.2.7, 5.2.9, 5.4) or
  • (5.6) an expression that is not a null pointer constant and is of a type other than cv void * is converted to enter a pointer to T or a reference to T using the standard conversion (section 4), dynamic_cast (5.2.7) or static_cast (5.2 .9) or
  • (5.7) the member access operator is applied to an expression of type T (5.2.5) or
  • (5.8) an operator of type (5.2.8) or a sizeof operator (5.3.3) is applied to an operand of type T or
  • (5.9) a function with a return type or an argument type of type T is defined by (3.1) or called (5.2.2) or
  • (5.10) a class with a base class of type T is defined (section 10) or
  • (5.11) An lvalue of type T is assigned to (5.18) or
  • (5.12) type T is the subject of the alignment expression (5.3.6) or
  • (5.13) an exception declaration is of type T, a reference to T, or a pointer to T (15.3).

None of them say that T must be complete in order to declare a pointer to an element of T

+5
source share

All Articles