Must consteval constructor initialize all data members?
Asked Answered
Z

1

8

In the next program struct B has immediate consteval default constructor, which does not initialize i field. Then this constructor is used to make a temporary and its i field remains untouched:

struct B {
    bool b = true;
    int i;
    consteval B() {}
};

static_assert( B{}.b );

Clang and MSVC are fine with it. But GCC complains:

 error: 'B{true}' is not a constant expression
    7 | static_assert( B{}.b );
      |                  ^
error: 'B()' is not a constant expression because it refers to an incompletely initialized variable

Demo: https://gcc.godbolt.org/z/x4n6ezrhT

Which compiler is right here?

Update:

I reported this issue to GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104512 And it was closed with the explanation

This gives the hint that both MSVC and clang are incorrect really. EDG also implements correctly static_assert not being an immediate function context.

Zane answered 11/2, 2022 at 18:58 Comment(0)
G
6

From cppreference's consteval specifier (since C++20):

The consteval specifier declares a function or function template to be an immediate function,
...
An immediate function is a constexpr function, and must satisfy the requirements applicable to constexpr functions or constexpr constructors, as the case may be.

And if we go to cppreference's constexpr specifier (since C++11):

A constexpr function must satisfy the following requirements:
...
A constexpr constructor whose function body is not =delete; must satisfy the following additional requirements:
...
for the constructor of a class or struct, every base class sub-object and every non-variant non-static data member must be initialized.

However, as @user17732522 accurately pointed out in a comment below, this last requirement applies only until C++20.

So I would say i doesn't need to be initialized in this case (Clang/MSVC are correct, gcc is wrong).

Gleiwitz answered 11/2, 2022 at 19:51 Comment(2)
The initialization requirement applies only before C++20.Lublin
@Lublin True. I hadn't noticed. I'll update my answer. Many thanks for the comment.Gleiwitz

© 2022 - 2024 — McMap. All rights reserved.