考虑以下示例( 代码段 (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
上面的例子编译所有版本的
g++
之前 g++ 10.x
,并且从未在 clang++
下编译.错误信息是:error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
live example on godbolt.org
错误类型是有道理的,如
x
永远不是 foo
主体中的常量表达式, 然而:X::get()
被标记 constexpr
并且它不依赖于 x
的状态; const X&
至 const X
使代码与每个编译器一起编译 (on godbolt.org) 片段 (1) . 当我标记
X::get()
时,它变得更有趣了如 static
( (on godbolt.org) 片段(2))。随着这一变化,g++
的所有测试版本(包括主干)编译,而 clang++
仍然总是无法编译。所以,我的问题:
g++ 9.x
正确接受 片段 (0) ? g++ 9.x
和 g++ trunk
正确接受 片段(2) ? 最佳答案
Is g++ 9.x correct in accepting snippet (0)?
不。
Are all compilers correct in accepting snippet (1)? If so, why is the reference significant?
对,他们是。
常量表达式不能使用 id 表达式命名引用,该引用没有先前的常量表达式初始化或在常量表达式评估期间开始其生命周期。 [expr.const]/2.11 ( same in C++20 )
如果您在不涉及任何左值到右值转换的情况下命名非引用变量,则情况并非如此。
x.get()
仅指x
作为左值并且只调用一个 constexpr
实际上不访问 x
的任何成员的函数,所以没有问题。Are g++ 9.x and g++ trunk correct in accepting snippet (2)?
否,因为表达式仍包含子表达式
x
这违反了上述规则。
关于c++ - 通过引用调用 `constexpr` 成员函数 - clang vs gcc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60454862/