具有相同基础类类型的条件运算符
Conditional operator with same underlying class type
这个程序应该输出 0 还是 1?在我对 C++14 标准中引用段落的阅读和理解中,它应该打印 1,但 GCC 和 clang 都打印 0(因为推断的类型是A const
而不是A const&
):
#include <iostream>
struct A {};
int main()
{
A a;
A const& ra = std::move(a); // #1
std::cout << std::is_same<decltype(true ? ra : std::move(a)),
A const&>::value; // Prints 0
}
在本例中,ra
是A const
的左值,std::move(a)
是A
x值,两者都是类类型。根据关于条件运算符的标准(强调我的),结果应该是类型A const
的lvalue
,因此decltype
结果必须A const&
:
[expr.cond]/3否则,如果第二个和第三个操作数具有不同的类型,并且具有(可能符合 cv 条件的)类 类型,或者如果两者都是相同值类别的 GL 值并且除 CV 资格外属于同一类型,则 尝试将每个操作数转换为另一个操作数的类型。确定过程 是否可以转换类型 T1 的操作数表达式 E1 以匹配类型的操作数表达式 E2 T2 定义如下:
— 如果E2 是左值:如果 E1 可以隐式转换为 E2(第 4 条),则可以将 E1 转换为匹配 键入"对 T2 的左值引用">,但受以下约束:在转换中,引用必须直接绑定 (8.5.3) 到左值。
[...]
在这种情况下,E2是ra
,这是一个左值,另一个可以隐式转换为"对 T2 的左值引用">,如第// #1
行所示。"对 T2 的左值引用">被翻译为A const&
,因此,std::move(a)
直接绑定到类型A const
的左值,转换后,两个操作数具有相同的类型和值类别,因此:
[expr.cond]/3如果第二个和第三个操作数是相同值类别的 glvalue 并且具有相同的类型,则结果属于该类型和值类别 [...]。
因此,运算符结果应该是左值,decltype
结果应该是引用,因此程序应该打印 1。
这个问题措辞很尴尬。相反,您应该询问表达式true ? ra : std::move(a)
的类型和值类别应该是什么。这个问题的答案是A const
型的 prvalue .这随后意味着程序应该打印 0,因为我认为每个编译器都正确。
?:
的规则相当复杂。在这种情况下,我们有两个类类型的表达式,我们尝试根据有限的规则子集查看是否可以相互转换。
尝试转换ra
→std::move(a)
失败。我们首先尝试使用不能直接绑定到ra
的目标类型是A&&
。然后,我们在 (3.3.1) 中尝试备份计划,因为这两个表达式具有相同的底层类类型,但我们的目标表达式至少不像源表达式那样符合 cv 资格,因此这也失败了。
尝试转换std::move(a)
→ra
失败(3.1),因为我们需要直接绑定到左值(我们可以将右值绑定到常量左值引用,但这里我们需要绑定左值)。但是,(3.3.1) 备份成功,因为现在目标类型至少与源一样符合 cv 条件。
因此,我们应用转换并继续,就好像第二个操作数是A const
类型的左值,但第三个操作数现在是A const
类型的 prvalue(而不是类型A
的 xvalue)。
(4) 失败,因为它们不属于同一值类别。
因此,结果是一个价值。由于它们具有相同的类型,因此结果是该类型:A const
.
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 如何确保接受的C++模板类型使运算符重载?
- C++中的条件运算符 ( ? : ) 可以编译时吗?
- C2679 二进制"<<":未找到采用右操作数类型的运算符
- 使用类型id运算符的最佳替代方法
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- 何时包含内置类型和运算符的标头?
- 如何为缺少预定义运算符而不扩展命名空间"std"的标准类型定义运算符>> (istream &, ...)?
- C++等效于 C# 的 "?." 空条件运算符
- 如何使用common_type和模板递归类型重载运算符+
- 具有相同基础类类型的条件运算符
- 条件运算符的返回类型和两阶段查找
- C++模板元编程:模板类型上的编译时条件运算符
- 使用三元条件运算符时操作数类型不兼容
- 具有混合数据类型的条件运算符
- 为什么在条件运算符(?:)中,第二个和第三个操作数必须具有相同的类型
- '?:'(三元/条件运算符)的结果类型是什么?
- 与类型转换运算符一起使用时条件运算符"?:"的编译器错误
- VS 2012中的条件运算符类型转换
- 用不同类型作为参数的条件运算符