This question seems related to an existing one, but I do not understand the "portable workaround" provided in the answer there (involving const auto this_ = this;
) and moreover I think the following example is easier to follow.
I am playing with the following snippet of C++17 code (live demo):
#include <iostream>
struct Test {
const char* name_{nullptr};
const Test* src_{nullptr};
constexpr Test(const char* name) noexcept
: name_{name}
{}
constexpr Test(const Test& src) noexcept
: src_{&src}
{
name_ = src_->name_;
src_ = nullptr;
}
};
template<char c>
void print_constexpr_char() {
std::cout << c << std::endl;
}
int main() {
constexpr const char* in = "x";
constexpr auto foo = Test{in};
constexpr auto bar = Test{foo};
std::cout << bar.name_ << std::endl;
print_constexpr_char<bar.name_[0]>();
return 0;
}
Compilation fails with GCC 7.2 while Clang 5.0.0 does not see any problem. The GCC error essentially reads
error: the value of 'bar' is not usable in a constant expression
note: 'bar' used in its own initializer
I am even more confused after realizing that removing the final print_constexpr_char
makes the code compile although it still contains the line constexpr auto bar = Test{foo};
which GCC used to complain about ("used in its own initializer").
- Which compiler is correct here?
- How to understand the GCC note (if not a bug) that "using in its own initializer" is harmful iff the result is subsequently used in a constant expression?
- Is there a valid way/workaround to use pointers in a
constexpr
constructor as an intermediate stage before transforming the object under construction into the final state which can be stored in aconstexpr
variable?