假设我们有
template <typename T>
struct Foo
{};
和
struct Bar
{
template <typename T>
operator Foo<T>() const { return Foo<T>(); }
};
和
template <typename T>
Foo<T> Baz(T const&) { return Foo<T>(); }
然后,
true ? Bar() : Baz(some_expr_of_type_double)
的类型为Foo<double>
,因为Bar
可转换为Foo<double>
。此技巧用于查询some_expr_of_type_double
的类型而不对其进行评估。确定
a ? b : c
类型的规则是什么?我会很感激该标准的相关部分(我没有拷贝)。除了“typeof(b)
必须可以明确转换为typeof(c)
或反之亦然”之外,还有其他吗?
最佳答案
这是相关的规范:
5.16条件运算符[expr.cond]
右到左。第一个表达
隐式转换为 bool
(第4节)。它被评估,如果
这是真的,
条件表达式就是值(value)
第二个表达式的值,否则
第三个表达式的值。全部
第一个表达式的副作用
除了销毁
临时(12.2)发生在
第二或第三个表达式是
评估。只有第二个
然后评估第三个表达式。
—第二个或第三个操作数(但不是两个)都是throw-expression(15.1);结果是另一个的类型,并且是一个右值。
—第二和第三操作数的类型均为void;结果是void类型,是一个右值。
[注意:这包括两个操作数均为throw-expressions的情况。 ]
3.a:如果E2是左值:如果可以将E1隐式转换为“对T2的引用”类型,则可以将E1转换为与E2匹配,但要满足以下条件:在转换中,引用必须直接绑定(bind)( 8.5.3)至E1。
3.b:如果E2是右值,或者上述转换无法完成:
3.b.1:如果E1和E2具有类类型,并且基础类类型相同,或者一个是另一个的基类:如果T2的类与以下类型相同,则可以将E1转换为匹配E2, T1的类别或T1的基本类别,并且T2的cv限定与t1的cv限定相同,或者具有比T1的cv限定更大的cv限定。如果应用了转换,则将E1更改为类型T2的右值,该值仍然引用原始源类对象(或其适当的子对象)。 (注意:也就是说,不进行任何复制。)
3.b.2:否则(即,如果E1或E2具有非类类型,或者它们都具有类类型,但基础类既不相同又不是另一个的基类):可以将E1转换为如果可以将E1隐式转换为表达式E2,如果将E2转换为右值(或者如果E2是右值,则具有它的类型),则匹配E2。
使用此过程,确定是否可以将第二操作数转换为与第三操作数匹配,以及是否可以将第三操作数转换为与第二操作数匹配。如果两者都可以转换,或者一个都可以转换但转换不明确,则说明程序格式错误。如果两个都不能转换,则操作数保持不变,并按如下所述进行进一步检查。如果仅可能进行一次转换,则将该转换应用于所选的操作数,并且在本节的其余部分中,将使用转换后的操作数代替原始操作数。
6.a:第二和第三操作数具有相同的类型;结果就是这种类型。
6.b:第二和第三操作数具有算术或枚举类型;通常的算术转换将其转换为通用类型,结果就是该类型。
6.c:第二和第三操作数具有指针类型,或者一个具有指针类型,另一个是空指针常量;执行指针转换(4.10)和资格转换(4.4),以将其转换为复合指针类型(5.9)。结果是复合指针类型。
6.d:第二和第三操作数具有指向成员类型的指针,或者一个具有指向成员类型的指针,另一个是空指针常量;执行指向成员转换(4.11)和限定转换(4.4)的指针,以将它们转换为通用类型,其cv-qualification应与第二或第三个操作数的cvqualification相匹配。结果是普通类型的。
关于c++ - `a ? b : c`是什么类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4149335/