2

Sample 1

template <typename T>
struct A
{

    constexpr A() = default;
    T x;
};

int main(){
    static_assert(A<int>{}.x == int{}, "FAILED");
}

Sample 2

struct A
{
    constexpr A() = default;
    int x;
};

int main(){
    static_assert(A{}.x == int{}, "Not Equal");
}

I am confused as to how the first sample compiles and passes the static assert, while the second one fails to compile as mentioned in the constexpr defaulted default constructors with Error: defaulted definition of default constructor is not constexpr.

Tried reading the following but couldn't understand as to how first one works and other doesn't. http://eel.is/c++draft/class.ctor#class.default.ctor-4

A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) to create an object of its class type ([intro.object]), when it is needed for constant evaluation ([expr.const]), or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer and an empty compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed. If that user-written default constructor would satisfy the requirements of a constexpr constructor ([dcl.constexpr]), the implicitly-defined default constructor is constexpr. Before the defaulted default constructor for a class is implicitly defined, all the non-user-provided default constructors for its base classes and its non-static data members are implicitly defined. [ Note: An implicitly-declared default constructor has an exception specification ([except.spec]). An explicitly-defaulted definition might have an implicit exception specification, see [dcl.fct.def]. — end note ]

Thank You!

CodeCollector
  • 468
  • 2
  • 13
  • 1
    If you declare a variable `constexpr A z;`, you'll get a compiler error about `x` not being initialized, so I'm inclined to think it is a compiler bug. – 1201ProgramAlarm Jun 06 '20 at 16:28
  • I have tried it on `gcc, clang, mvsc` using godbolt.org and sample 1 compiled on all of them, so I don't think it is a bug. However I tried the line that you sent, it indeed doesn't work but if I try `constexpr A z{}` then it works. – CodeCollector Jun 06 '20 at 16:40

1 Answers1

1

The following can shed some light on the issue:

int main(){
    constexpr A<int> a;
}

Attempting to call the constexpr constructor produces this error (gcc):

<source>: In function 'int main()':
<source>:12:22: error: uninitialized 'const a' [-fpermissive]
   12 |     constexpr A<int> a;
      |                      ^
<source>:4:8: note: 'const struct A<int>' has no user-provided default constructor
    4 | struct A
      |        ^
<source>:7:15: note: constructor is not user-provided because it is explicitly defaulted in the class body
    7 |     constexpr A() = default;
      |               ^
<source>:8:7: note: and the implicitly-defined constructor does not initialize 'int A<int>::x'
    8 |     T x;
      |       ^

However, if I am not missing something, the constexpr constructor should already be an error, because it cannot be constexpr (see here).

Both gcc and clang accept your code, but both produce an error for attempting to call the constexpr constructor. I suppose it is a compiler bug.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • For sample 1, `constexpr A a;` is giving me, `constexpr variable cannot have non-literal type 'const A' (aka 'const A >')` which makes sense with reference to [link](https://stackoverflow.com/questions/27123306/is-it-possible-to-use-stdstring-in-a-constexpr#:~:text=As%20of%20C%2B%2B20,any%20sequence%20of%20char%20objects.) – CodeCollector Jun 06 '20 at 17:19
  • @CodeCollector oh, then I was wrong. will remove that part – 463035818_is_not_an_ai Jun 06 '20 at 17:23