I'm trying to change the active member of a constexpr union using construct_at and get the following error when constructor initializes it's member using initializer list vs. member. Can someone explain why?
#include <memory>
struct Z {
#if 1 // If this changes to zero it does not compile
constexpr Z(int x) : y(x){
}
#else
constexpr Z(int x) {
y = x;
}
#endif
int y;
};
struct W {
constexpr W(int x) {
y = x;
}
W(const W&) {}
int y;
};
union U {
Z z;
W w;
constexpr U(int z) : w(z) {
}
};
constexpr int func() {
constexpr U u(10);
std::construct_at(&u.z, 10);
// ::new (&u.z) Z(10);
return u.z.y;
}
int main() {
static_assert(func() == 1);
}
Error:
source>: In function 'int main()':
<source>:37:26: error: non-constant condition for static assertion
37 | static_assert(func() == 10);
| ~~~~~~~^~~~~
<source>:37:23: in 'constexpr' expansion of 'func()'
<source>:31:21: in 'constexpr' expansion of 'std::construct_at<const Z, int>((& u.U::z), 10)'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/stl_construct.h:97:14: in 'constexpr' expansion of '((Z*)<anonymous>)->Z::Z(<anonymous>)'
<source>:8:12: error: modifying a const object '((Z*)this)->Z::y' is not allowed in a constant expression
8 | y = x;
| ~~^~~
<source>:30:16: note: originally declared 'const' here
30 | constexpr U u(10);
| ^
Compiler returned: 1