条件运算符检查两个方向的转换。在这种情况下,由于您的构造函数是显式的(因此?:
不是模棱两可的),因此使用从Foo
to的转换int
,使用转换为的转换函数double
:这有效,因为在应用转换函数后,标准转换将转换double
为int
(截断)如下。?:
在您的情况下,结果是int
,并且具有值6
。
在第二种情况下,由于操作数具有 type double
,因此不会发生这种尾随转换 to int
,因此结果类型的?:
typedouble
具有预期值。
要理解“不必要的”转换,您必须了解像您这样的表达式?:
被评估为“无上下文”:在确定它的值和类型时,编译器不会认为它是return
返回 a 的函数的操作数double
.
编辑:如果你的构造函数是隐式的会发生什么?该?:
表达式将是不明确的,因为您可以将 an 转换int
为类型的右值Foo
(使用构造函数),并将 a转换Foo
为类型的右值int
(使用转换函数)。标准说
使用该过程,确定是否可以转换第二操作数以匹配第三操作数,以及是否可以转换第三操作数以匹配第二操作数。如果两者都可以转换,或者一个可以转换但转换不明确,则程序格式错误。
解释您如何Foo
转换为的段落int
:
5.16/3
关于condition ? E1 : E2
:
否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是 cv 限定的)类类型,则会尝试将这些操作数中的每一个转换为另一个的类型。[...] 如果 E1 可以隐式转换为表达式 E2 将具有的类型(如果 E2 转换为右值(或它具有的类型,如果 E2 是右值)),则 E1 可以转换为匹配 E2。
4.3
关于“隐式转换”:
T t = e;
对于某些发明的临时变量 t,当且仅当声明格式正确时,表达式 e 才能隐式转换为类型 T。
8.5/14
关于拷贝初始化(T t = e;
)
如果源类型是(可能是 cv 限定的)类类型,则考虑转换函数。列举了适用的转换函数 (13.3.1.5),并通过重载决议 (13.3) 选择最佳转换函数。调用如此选择的用户定义转换将初始化表达式转换为正在初始化的对象。如果转换无法完成或不明确,则初始化格式错误。
13.3.1.5
关于转换函数候选
考虑了 S 及其基类的转换函数。那些未隐藏在 S 中并产生类型 T 或可以通过标准转换序列 (13.3.3.1.1) 转换为类型 T 的类型是候选函数。