我有一个函数引用
T*
:void f(T *&t);
。当我用带抛出的条件表达式调用它时,f(t == nullptr ? throw "nullptr" : t)
,程序无法编译:
error: cannot bind non-const lvalue reference of type 'T*&' to an rvalue of type 'T*'
note: initializing argument 1 of 'f(T*&)'
但是用
f(t)
替换上面的调用就可以编译得很好。
这是为什么呢?整个表达式应该与非抛出具有相同的类型 操作数:https://en.cppreference.com/w/cpp/language/operator_other。从链接中,
Either E2 or E3 (but not both) is a (possibly parenthesized) throw-expression. The result of the conditional operator has the type and the value category of the other expression.
可重现的示例:https://godbolt.org/z/9MW1Kevxz
#include <iostream>
using namespace std;
struct T {
int i;
};
void f(T*& t) {
t->i = 2;
}
int main()
{
T *t = new T{5};
f(t == nullptr ? throw "hi" : t);
return 0;
}
在 x86-64 上使用 gcc 9.4 失败。
这是CWG 1550。 C++ 标准过去要求三元运算符的结果是另一个(非
throw
)操作数的类型,但值类别始终是纯右值。最终这一点发生了改变,现在保留了另一个操作数的值类别,但似乎 GCC 仅在版本 10 及更高版本中实现了更改(在 godbolt 中在线查看)。