C++ why can't classes with const reference member variables be created using constexpr?

Viewed 144

In the following code, I try to store a const reference to another class:

struct A {
};

struct B {
    constexpr B(A const & _a) : a(_a) {}
        
    A const &  a;
};

int main() {
    constexpr A s1;
    constexpr B s2{s1};
}

however, the compiler (gcc 11.1) complains with:

cctest.cpp: In function ‘int main()’:
cctest.cpp:12:22: error: ‘B{s1}’ is not a constant expression
   12 |     constexpr B s2{s1};
      |

and I can't work out why s1 is not considered a constant expression. s1 itself is a constexpr in the code. I know this probably has something to do with lifetimes of the references, but I can't work out the logic. In the code that this example came from, I don't want to store a copy of A, I really do just want a reference or (smart) pointer. So:

  1. Why is s1 not a constant expression?
  2. What is the best practice way of handling this?

Many thanks!

1 Answers

Clang 12.0.0+ gives a descriptive note about the issue:

note: address of non-static constexpr variable 's1' may differ on each invocation of the enclosing function; add 'static' to give it a constant address

So you need to add a static here:

struct A {
};

struct B {
    constexpr B(A const & _a) : a(_a) {}
        
    A const &  a;
};

int main() {
    constexpr static A s1;
    constexpr B s2{s1};
}
Related