问题
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?
回答1:
GCC is correct to reject the code (however the error message could use some work). You cannot use the address of a variable in a constant expression unless that variable has static storage duration.
foo
is not static. If you move it outside of main
, things will work. Demo
The line marked below is the problem:
constexpr Test(const Test& src) noexcept
: src_{&src} <--- That
Standard reference: (Emphasis mine)
[expr.const]
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
(5.2) — if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (8.7), the address of a function, or a null pointer value,
来源:https://stackoverflow.com/questions/46688093/constexpr-variable-used-in-its-own-initializer-clang-vs-gcc