Why initialization of constexpr variable from non constexpr variable succeeds in case of class

231 Views Asked by At

I have learnt about constexpr variables in c++ and read that int i =0; constexpr int j = i; fails because i is not a constant expression which makes sense. But then when I did the same with a variable of a class, it worked.

struct C{};
int main()
{
    int i = 0; //i is not a constant expression as expected 
    //constexpr int j = i; //this fails AS EXPECTED

    C c; 
    constexpr C d = c; //WHY DOESN'T THIS FAIL?? 
}

As you can see, constexpr C d = c; compiles without any problem unlike constexpr int j = i; even though c is also not a constant expression.

I want to know the reason behind this.

2

There are 2 best solutions below

9
user12002570 On BEST ANSWER

I want to know the reason behind this.

Because the class C has an implicit constexpr copy constructor constexpr C::C(const C&) that can be used in constexpr context like this.

Basically the initialization constexpr C d = c; is a constexpr context and the constexpr ctors are designed exactly for these purposes.


You can also see this by looking at the generated code at cppinsights:

struct C
{
  // inline constexpr C() noexcept = default;
  // inline constexpr C(const C &) noexcept = default;
};

As we can see in the above generated code, C has implicitly declared constexpr constructors that can be used in constexpr contexts.


From constexpr:

A constexpr variable must satisfy the following requirements:

  • ...
  • the full-expression of its initialization, including all implicit conversions, constructors calls, etc, must be a constant expression
0
Benjamin Buch On

Its valid because the initialization of d doesn't depend on the value of c since c contains no data that exists while runtime.

struct A{
    static int x;
};

int A::x = 5;

struct B{
    int x = 5;
};

int main() {
    A a1;
    constexpr A a2 = a1; // a1 contains no runtime data: okay

    B b1;
    constexpr B b2 = b1; // b1 contains runtime data: error
}
g++ main.cpp 
main.cpp: In function ‘int main()’:
main.cpp:16:22: error: the value of ‘b1’ is not usable in a constant expression
   16 |     constexpr B b2 = b1; // a1 containes runtime data: error
      |                      ^~
main.cpp:15:7: note: ‘b1’ was not declared ‘constexpr’
   15 |     B b1;
      |       ^~

You can find the list of requirements for a constant expression at: