您的代码不明确,不应编译(它是不规范的每 13.3.3:2)。
左值到右值转换与恒等转换具有相同的等级,因此(根据 13.3.3:1)无法在它们之间进行选择。
科莫 C++ http://www.comeaucomputing.com/tryitout(可能是最符合标准的编译器)给出以下错误:
"ComeauTest.c", line 11: error: more than one user-defined conversion from "B" to
"A" applies:
function "B::operator A()"
function "B::operator A &()"
(A) b;
^
以下是该标准的相关文本:
c++11 /questions/tagged/c%2b%2b11
13.3.3 最佳可行函数[over.match.best]
[...]给定这些定义,一个可行函数 F1 被定义为比另一个可行函数 F2 更好的函数 [...]
2 -
如果恰好有一个可行函数比所有其他可行函数都更好,那么它就是
由重载决议选择的一个;否则调用的格式不正确。
定义本身很复杂,但用户定义的转换有两点需要注意:
一、应用用户自定义转换作为转换序列指定分解为序列S_a - U - S_b
一个标准转换序列,后跟一个用户定义的转换,然后是另一个标准转换序列。这涵盖了所有情况;在一个转换序列中不能有多个用户定义的转换,并且标准转换序列可以是“身份转换”,即不需要转换。
其次,在比较用户定义的转换序列时,唯一重要的部分是第二个标准转换序列。这是在 13.3.3 中:
c++11 /questions/tagged/c%2b%2b11
13.3.3 最佳可行函数[over.match.best]
[...] 可行函数 F1 被定义为比另一个可行函数更好的函数
F2 如果 [...]
- 上下文是通过用户定义的转换进行的初始化(参见 8.5、13.3.1.5 和 13.3.1.6)
从 F1 的返回类型到目标类型(即
正在初始化的实体)是比标准转换序列更好的转换序列
F2 到目标类型的返回类型。
以及 13.3.3.2 中:
c++11 /questions/tagged/c%2b%2b11
13.3.3.2 对隐式转换序列进行排序 [over.ics.rank]
3 - 两个相同形式的隐式转换序列是无法区分的转换序列,除非其中之一
以下规则适用:[...]
- 如果用户定义的转换序列 U1 包含相同的用户定义的转换函数或构造函数或聚合,则它们是比另一个用户定义的转换序列 U2 更好的转换序列
U1的初始化和第二标准转换序列优于第二标准
U2的转换序列。
所以在比较转换序列时U1 = (S1_a - U'1 - S1_b)
and U2 = (S2_a - U'2 - S2_b)
唯一重要的是相对排名S1_b
and S2_b
;达到用户定义的转换参数所需的标准转换序列并不重要。
所以可能的转换顺序为(A) b
,需要一个转换序列产生B -> A
, are:
U1: B -> B [identity], B::operator A() [user-defined], A -> A [identity]
U2: B -> B [identity], B::operator A &() [user-defined], A & -> A [rvalue-to-lvalue]
现在,我们如何对标准转换序列进行排序?需要查看的地方是 13.3.3.1.1 中的表 12,它指定左值到右值转换与恒等转换具有相同的等级(“精确匹配”)。因此无法区分两个用户定义的转换序列,并且程序是格式错误的。
Sidebar
在对用户定义的转换序列进行排序方面,13.3.3 和 13.3.3.2 有什么区别?
13.3.3 允许编译器区分不同的用户定义的转换运算符; 13.3.3.2 允许编译器区分不同的功能每个都需要在其参数中进行用户定义的转换。
所以,在代码中
struct A {
operator int();
operator float();
} a;
void f(int);
f(a);
13.3.3 适用并且A::operator int()
被选择超过A::operator float()
;在代码中
struct A {
operator int();
} a;
void f(int);
void f(double);
f(a);
13.3.3.2 适用并且void f(int)
被选择超过void f(double)
。然而在代码中
struct A {
operator int();
operator float();
} a;
void f(int);
void f(double);
f(a);
尽管 13.3.3 更喜欢A::operator int() -> void f(int)
over A::operator float() -> void f(int)
and float -> double
over int -> double
,并且 13.3.3.2 更喜欢int -> int
over int -> double
and float -> double
over float -> int
,没有办法区分int -> int
and float -> double
转换序列(因为它们既不包含相同的用户定义转换运算符,也不包含相同的重载f
),因此代码格式不正确。