Consider the following simplified code:
template <class T> class Foo { T t; const T* t_ptr;public: constexpr Foo(T t): t(t), t_ptr(&this->t) {} constexpr Foo(const Foo& foo): t(foo.t), t_ptr(&this->t) {} constexpr T get_t() const { return *t_ptr; }};template <class T> constexpr Foo<T> foo(T t) { return Foo<T>(t);}constexpr auto f = foo(1);static_assert(f.get_t() == 1);It successfully compiles withClang and MSVC butGCC 15 reports an error:
<source>:16:25: error: non-constant condition for static assertion 16 | static_assert(f.get_t() == 1); | ~~~~~~~~~~^~~~<source>:16:22: in 'constexpr' expansion of 'f.Foo<int>::get_t()'<source>:8:17: error: the value of 'f' is not usable in a constant expression 8 | return *t_ptr; | ^~~~~<source>:15:16: note: 'f' used in its own initializer 15 | constexpr auto f = foo(1); | ^Compiler returned: 1Is this code valid? Is this a bug in GCC? Is there a workaround to make constexpr structs that contain a pointer to its own member work?
- 2
1 Answer1
I think it is a gcc bug.
Some variants pass when calling constructors directlyDemo
I think gcc badly implements the note fromcopy_elision (code "similar" to yours).
In constant expression and constant initialization, copy elision is never performed.
Sign up to request clarification or add additional context in comments.
3 Comments
eyelash
Does anyone know if this bug is already reported on the GCC Bugzilla or if the GCC developers are aware of it?
Fedor
Nothing changes in any of compilers, if copy constructor is deleted
constexpr Foo(const Foo& foo) = delete;gcc.godbolt.org/z/KGd6jzM4fExplore related questions
See similar questions with these tags.
