C++11 通过初始标准转换序列区分用户定义的转换序列
该标准似乎提供了两条规则,用于区分涉及用户定义转换运算符的隐式转换序列: 13.3.3最佳可行功能[超过.匹配.最佳] […]可行函数F1被定义为比另一个可行函数更好的函数 F2如果[…]C++11 通过初始标准转换序列区分用户定义的转换序列,c++11,c++,constructor,implicit-conversion,language-lawyer,conversion-operator,C++11,C++,Constructor,Implicit Conversion,Language Lawyer,Conversion Operator,该标准似乎提供了两条规则,用于区分涉及用户定义转换运算符的隐式转换序列: 13.3.3最佳可行功能[超过.匹配.最佳] […]可行函数F1被定义为比另一个可行函数更好的函数 F2如果[…] 上下文是用户定义转换的初始化(见8.5、13.3.1.5和13.3.1.6)和 从F1返回类型到目标类型的标准转换顺序(即 实体(正在初始化)是一个比标准转换序列更好的转换序列 将F2的返回类型设置为目标类型 13.3.3.2隐式转换序列排名[超过ics排名] 3-两个相同形式的隐式转换序列是不可区分的
- 上下文是用户定义转换的初始化(见8.5、13.3.1.5和13.3.1.6)和 从F1返回类型到目标类型的标准转换顺序(即 实体(正在初始化)是一个比标准转换序列更好的转换序列 将F2的返回类型设置为目标类型
- 如果用户定义的转换序列U1包含相同的用户定义的转换函数或构造函数或聚合,则用户定义的转换序列U1比另一个用户定义的转换序列U2更好 U1的初始化和第二个标准转换顺序优于第二个标准 U2的转换序列
f
),每个函数的参数都需要用户定义的转换(请参见我的侧栏)
是否有其他规则可以区分用户定义的转换序列?回答at表明13.3.3.2:3可以根据隐式对象参数(转换运算符)或单个非默认参数(构造函数)或聚合初始化的cv限定来区分用户定义的转换序列,但我不认为这有什么关系,因为这需要比较各个用户定义的转换序列的第一个标准转换序列,而该标准似乎没有提到
假设S1比S2好,其中S1是U1的第一个标准转换序列,S2是U2的第一个标准转换序列,那么U1比U2好吗?换句话说,这个代码是否格式正确
struct A {
operator int();
operator char() const;
} a;
void foo(double);
int main() {
foo(a);
}
(4.5.1)、(3.0)和(4.3.10.1)接受它,更喜欢非常量限定的
A::operator int()
,但我希望它会被拒绝,因为它不明确,因此格式不正确。这是标准中的缺陷还是我对它的理解中的缺陷?这里的技巧是,从类类型转换为非类类型实际上并不将任何用户定义的转换作为隐式转换序列进行排序
struct A {
operator int();
operator char() const;
} a;
void foo(double);
int main() {
foo(a);
}
在表达式foo(a)
中,foo
显然命名了一个非重载的非成员函数。调用需要使用单个表达式a
,对double
类型的函数参数进行复制初始化(8.5p14),该表达式是类类型a
的左值
由于目标类型double
不是cv限定类类型,但源类型a
是,候选函数由第13.3.1.5节定义,其中S=a
和T=double
。仅考虑类A
中的转换函数和A
的任何基类。在以下情况下,转换函数位于候选函数集中:
- 它不隐藏在类
中,并且A
- 它不是显式的(因为上下文是复制初始化),并且
- 标准转换序列可以将函数的返回类型(不包括任何引用限定符)转换为目标类型
double
A::operator int(); // F1
A::operator char() const; // F2
使用13.3.1p4中的规则,每个函数的参数列表中只有隐式对象参数F1
的参数列表是“(对A
的左值引用)”,F2
的参数列表是“(对const A的左值引用
)”
接下来,我们检查功能是否可行(13.3.2)。每个函数在其参数列表中都有一个类型,并且有一个参数。每个参数/参数对是否都有隐式转换序列?当然可以:
:将隐式对象参数(类型左值引用到ICS1(F1)
)绑定到表达式A
(类型左值A
)A
:将隐式对象参数(对ICS1(F2)
的类型左值引用)绑定到表达式const A
(类型左值A
)A
ICS1(F2)
的引用类型比ICS1(F1)
的引用类型更符合cv,因此ICS1(F1)
优于ICS1(F2)
因此,F1
或A::operator int()
是最可行的函数。甚至没有对用户定义的转换(严格定义由SCS+(转换构造函数或转换函数)+SCS组成的IC类型)进行比较
现在,如果foo
被重载,则需要比较参数a
上的用户定义转换。s