![](/img/trans.png)
[英]constexpr function with unused reference argument – gcc vs clang
[英]Invoking `constexpr` member function through reference - clang vs gcc
考虑以下示例(代码段 (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
上面的示例使用g++ 10.x
之前的所有g++
版本进行编译,并且从未在clang++
下clang++
。 错误信息是:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
错误类型是有道理的,因为x
从来不是foo
主体中的常量表达式,但是:
X::get()
被标记为constexpr
并且它不依赖于x
的状态;
将const X&
更改为const X
会使代码与每个编译器(在 Godbolt.org 上)片段 (1)一起编译。
当我将X::get()
标记为static
( (在 Godbolt.org 上)片段 (2)时,它变得更加有趣。 随着这一变化,所有经过测试的g++
版本(包括主干)都可以编译,而clang++
仍然总是无法编译。
所以,我的问题:
g++ 9.x
在接受代码段 (0) 时是否正确?
所有编译器都正确接受代码片段 (1)吗? 如果是这样,为什么参考是重要的?
g++ 9.x
和g++ trunk
在接受代码片段 (2) 时是否正确?
g++ 9.x 在接受代码片段 (0) 时是否正确?
不。
所有编译器都正确接受代码片段 (1) 吗? 如果是这样,为什么参考是重要的?
对,他们是。
常量表达式不能使用 id 表达式命名引用,该引用没有先前的常量表达式初始化或在常量表达式评估期间开始其生命周期。 [expr.const]/2.11 (在 C++20 中相同)
如果您在不涉及任何左值到右值转换的情况下命名非引用变量,则情况并非如此。 x.get()
仅将x
称为左值,并且仅调用实际上并未访问x
任何成员的constexpr
函数,因此没有问题。
g++ 9.x 和 g++ trunk 在接受代码片段 (2) 时是否正确?
不,因为表达式仍然包含违反上述规则的子表达式x
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.