C++隐式转换序列形成规则存在矛盾?是否属于标准缺陷
关于C++隐式转换序列规则的矛盾疑问解答
首先明确:你观察到的标准文本冲突是真实存在的,主流编译器的判定也符合标准的设计意图,这一表述歧义属于C++标准的已知历史遗留问题。
为什么编译器会判定为重载歧义
重载决议的执行分为两个核心阶段:
- 可行函数筛选阶段:仅检查是否存在形式上符合要求的隐式转换序列,把实参转换为对应形参的类型。这个阶段仅关注类型、cv限定符、值类别这三类属性的匹配逻辑,不会检查转换用到的构造函数/转换函数是否被
delete、是否可访问这类合法性细节。
你的示例中,int到A的用户定义转换在形式上是存在的(A存在接受int的构造函数),int到B的用户定义转换也存在,因此#1和#2都会被判定为可行函数。 - 最佳可行函数筛选阶段:对所有可行函数的隐式转换序列的优先级进行比较。你的示例中两个转换序列都是用户定义转换,优先级完全相同,因此直接判定为重载歧义,不会进入后续的合法性检查步骤。
如果删掉#2的fun(B)重载,重载决议会直接选中#1,这时才会执行后续的合法性检查,抛出调用已删除函数A::A(int)的编译错误,也验证了转换序列本身确实被判定为存在。
标准文本的矛盾根源
你指出的三处标准条文确实存在表述冲突:
- [conv.general] p3 定义的普通隐式转换要求
T t=E;完全良构,会检查构造函数是否可调用、是否被删除等所有细节。 - 但[over.best.ics.general] p2 明确要求重载决议阶段的隐式转换序列仅考虑类型、cv、值类别三类属性,忽略其他细节。
- [over.best.ics.general] p1 又直接把重载决议用的隐式转换序列等价于[conv]定义的普通隐式转换,直接导致了规则矛盾。
这一问题已经被C++核心工作组(CWG)记录为标准缺陷,后续的标准版本会修正相关表述,明确重载决议场景下的隐式转换序列判定有专属规则,和普通语境的隐式转换定义并不完全等价,主流编译器的实现一直是符合标准设计意图的。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

