简体   繁体   中英

Why constinit of half-initialized struct does not work

struct A1 { int x;     int y; };
struct A2 { int x = 1; int y = 2; };
struct A3 { int x = 1; int y; };

constinit A1 a1; // x == 0, y == 0.
constinit A2 a2; // x == 1, y == 2.
          A3 a3; // x == 1, y == 0.
constinit A3 a4; // Error: illegal initialization of 'constinit' entity with a non-constant expression

int main() {}

What is the problem with a4 ? I mean a4.x should be initialized by a constant 1 (same as for a2 where it works) and a4.y by a constant 0 because a4 is a global static variable (same as for a1 where it works).

Now, considering that both MSVC and GCC fail to compile this code I assume the standard somehow forbids it. But any way I look at a4 its initial value is exact, constant and known at compile time so why the standard forbids us from declaring it as constinit )?

In addition to this, clang++ also rejects the first constinit ialization:

error: variable does not have a constant initializer
constinit A1 a1;  // x == 0, y == 0.

I think this is a case where we might be missing some wording.

To start with, there are three stages of initialization that happen ( [basic.start.static] ):

  1. Constant initialization
  2. If not that, zero-initialization (for static storage duration variables, like the ones in this question)
  3. If necessary, dynamic initialization

(1) and (2) together are static initialization, (3) is... well, dynamic. And what constinit does is ensure that there is no dynamic iniitialization, from [dcl.constinit] :

If a variable declared with the constinit specifier has dynamic initialization ([basic.start.dynamic]), the program is ill-formed.

And the rule for constant initialization is, from [expr.const] :

A variable or temporary object o is constant-initialized if

  • either it has an initializer or its default-initialization results in some initialization being performed, and
  • the full-expression of its initialization is a constant expression when interpreted as a constant-expression , except that if o is an object, that full-expression may also invoke constexpr constructors for o and its subobjects even if those objects are of non-literal class types.

With that said, let's go through the three types. Starting with the easiest:

struct A2 { int x = 1; int y = 2; };
constinit A2 a2; // x == 1, y == 2.

Here, we're initializing all the members, this is clearly constant initialization. Not really much of a question here.

Next:

struct A1 { int x;     int y; };
constinit A1 a1; // x == 0, y == 0.

Here, our default constructor does... nothing, there is no initialization. So this is not constant initialization. But zero-initialization happens and then there is no further initialization. There is certainly no dynamic initialization that has to take place here, so there is nothing for constinit to diagnose.

Lastly:

struct A3 { int x = 1; int y; };
constinit A3 a4; // Error: illegal initialization of 'constinit' entity with a non-constant expression

Prior to the adoption of P1331 , this initialization of a4 was clearly not constant initialization because constant initialization explicitly required fully initialized variables. But we don't have this requirement anymore, the rule was moved later - to when a4.y would actually be read.

But I think the intent in this case is very much that a4 is not constant initialized, due to it being partially uninitialized. This probably merits a core issue.

Given that it is not constant initialization, then we go into zero initialization. But after that, a4 still isn't fully initialized - because we have to set x to 1 . There is no provision for half-constant half-zero initialization. The rule is constant or, if not that, zero. Since this isn't (or, at least, shouldn't be) constant initialization, and zero-initialization is insufficient, a4 must undergo dynamic initialization. And thus, constinit should flag this case. gcc and msvc are correct here (clang erroneously rejects a1 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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