“ constexpr”变量“用于其自身的初始化程序”:Clang vs. GCC [英] `constexpr` variable "used in its own initializer": Clang vs. GCC
问题描述
这个问题似乎与现有的问题有关,但是我不理解答案(涉及 const auto this_ = this;
),而且我认为以下示例更容易理解。
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.
我正在使用以下C ++ 17代码段(实时演示):
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;
}
在GCC 7.2中编译失败,而Clang 5.0.0则看不到任何问题。 GCC错误本质上是
Compilation fails with GCC 7.2 while Clang 5.0.0 does not see any problem. The GCC error essentially reads
错误:'bar'的值不能在常量表达式中使用
error: the value of 'bar' is not usable in a constant expression
注意:在自己的初始化程序中使用的'bar'
note: 'bar' used in its own initializer
在意识到删除了final print_constexpr_char
使代码编译,尽管它仍包含GCC使用的行 constexpr auto bar = Test {foo};
抱怨(用在它自己的初始化程序中)。
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").
- 哪个编译器在这里正确?
- 如何理解GCC说明(如果不是bug),如果随后在常量表达式中使用结果,则在其自身的初始化程序中使用是有害的吗?
- 是否存在有效的在
constexpr
构造函数中使用指针作为中间阶段的方式/解决方法,然后将正在构造的对象转换为可以存储在constexpr中的最终状态
变量?
- 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?
推荐答案
GCC拒绝代码是正确的(但是错误消息可能会起作用)。除非该变量具有静态存储持续时间,否则无法在常量表达式中使用该变量的地址。
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
为不是静态的。如果将其移至 main
之外,则一切正常。 演示
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
标准参考:(强调我的)
[expr.const]
[expr.const]
一个常量表达式要么是glvalue核心常量表达式,指的是一个实体,该实体是一个常量表达式(定义如下)的允许的
结果,或者是一个值满足以下条件的
的prvalue核心常量表达式:
(5.2)-如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,即
超出此类对象末尾的地址(8.7),函数的地址或空指针值,
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,
这篇关于“ constexpr”变量“用于其自身的初始化程序”:Clang vs. GCC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!