C++ 当两名候选人具有相同的简历资格时,转换函数的初始化是否应该不明确?

C++ 当两名候选人具有相同的简历资格时,转换函数的初始化是否应该不明确?,c++,initialization,standards,overloading,language-lawyer,C++,Initialization,Standards,Overloading,Language Lawyer,clang和gcc都接受以下代码并选择A::operator B* struct B { }; struct A : B { operator A*(); operator B*(); }; A a; void* x = a; 我对标准的解读——特别是下面用粗体突出显示的句子——表明这种转换应该是模棱两可的 A::运算符A*和A::运算符B*都是重载解决方案的候选对象,因为A*和B*都可以通过标准转换转换为void*。由于隐含对象参数A&是唯一的参数,因此只考虑从隐含对象参

clang和gcc都接受以下代码并选择
A::operator B*

struct B
{
};

struct A : B
{
    operator A*();
    operator B*();
};

A a;
void* x = a;
我对标准的解读——特别是下面用粗体突出显示的句子——表明这种转换应该是模棱两可的

A::运算符A*
A::运算符B*
都是重载解决方案的候选对象,因为
A*
B*
都可以通过标准转换转换为
void*
。由于隐含对象参数
A&
是唯一的参数,因此只考虑从隐含对象参数转换为隐含对象参数的转换序列-忽略转换函数生成的类型。在这两种情况下,隐含对象参数都是初始值设定项表达式的类型
A
,而隐含对象参数是
A&
。如果两个转换序列相同,则无法区分这两个候选序列

8.5初始值设定人[dcl.init]

初始值设定项的语义如下所示。目标类型是正在创建的对象或引用的类型 已初始化,并且源类型是初始值设定项表达式的类型

-如果目标类型为[reference/array/class…][已删除的详细信息不适用于此场景]

-否则,如果源类型是(可能是cv限定的)类类型,则会考虑转换函数。 列举了适用的转换函数(13.3.1.5),并通过重载选择最佳转换函数 分辨率(13.3)。调用如此选择的用户定义转换来转换初始值设定项 表达式转换为正在初始化的对象如果转换无法完成或不明确,则 初始化格式不正确。

13.3.1.5通过转换函数进行初始化[over.match.conv]

在8.5中规定的条件下,作为非类类型对象初始化的一部分,转换 函数可被调用以将类类型的初始值设定项表达式转换为要创建的对象的类型 初始化重载解析用于选择要调用的转换函数。假设“cv1 “T”是被初始化对象的类型,“cv S”是初始化器表达式的类型,带S a 类类型,候选函数的选择如下所示:

-考虑了S及其基类的转换函数那些非显式转换 未隐藏在S中的函数产生类型T或可转换为类型T的类型 通过标准转换序列(13.3.3.1.1)是候选函数。对于直接初始化,这些 不隐藏在S中的显式转换函数,并生成类型T或可以 通过资格转换(4.4)转换为T型也是候选功能。转化 返回cv限定类型的函数被视为生成该类型的cv非限定版本 用于选择候选函数的此过程。返回“参考cv2”的转换函数 X“返回左值或X值,取决于参考类型,类型为“cv2 X”,因此 在选择候选函数的过程中,考虑产生X

参数列表有一个参数,即初始值设定项表达式。[注意:此参数将 与转换函数的隐式对象参数进行比较。-结束注释]

根据标准,这是不明确的吗

编辑:请注意,这是一个类似的问题,但与


区别在于,在我的示例中,两个转换函数具有相同的限定条件。

TLDR:当其他条件相同时,重载分辨率打破了转换函数从其返回值到目标类型的最佳转换的界限


所有参考文件均参考ISO/IEC 14882:2011(C++11)。初始化的行为:

void* x = a;
定义如下。首先,这是8.5初始化程序[dcl.init]中描述的初始化,符合p1中描述的语法。由于目标类型
void*
是非类类型,而源类型
a
是类类型,因此该特定初始值设定项的格式如第8.5页第7项所述:

否则,如果源类型是(可能是cv限定的)类类型,则会考虑转换函数。列举了适用的转换函数(13.3.1.5),并通过过载分辨率(13.3)选择了最佳转换函数。调用如此选择的用户定义转换,以将初始值设定项表达式转换为正在初始化的对象。如果转换无法完成或不明确,则初始化格式错误

“适用转换函数的枚举”详见13.3.1.5 p1:

在8.5中规定的条件下,作为非类类型对象初始化的一部分,转换 函数可被调用以将类类型的初始值设定项表达式转换为要创建的对象的类型 初始化。重载解析用于选择要调用的转换函数。假设“cv1 “T”是被初始化对象的类型,“cv S”是初始化器表达式的类型,带S a 类类型,候选函数的选择如下所示:

  • 考虑了S及其基类的转换函数。那些非显式转换 未隐藏在S中的函数产生类型T或可转换为类型T的类型 通过标准转换序列(13.3.3.1.1)是候选功能。对于直接初始化,这些 不隐藏在S中的显式转换函数