C++用户自定义类型转换重载解析的编译器行为差异及标准符合性疑问
C++用户自定义类型转换重载解析的编译器行为差异及标准符合性疑问
这确实是个挺有意思的问题,涉及到C++里用户自定义类型转换的重载解析规则,咱们一步步拆解来看:
首先先把你的测试代码贴出来,方便对照:
struct to_type; struct from_type{ operator to_type()const; }; struct to_type{ to_type() = default; to_type(const from_type&){} }; from_type::operator to_type()const{return to_type();} int main(){ from_type From; to_type To; To = From; return 0; }
先看你遇到的编译器行为差异:
- GCC默认模式:从v4.9.4到v13.0.0的版本,编译这段代码都不会报错,会直接调用
to_type的转换构造函数完成赋值; - Clang全版本:从v7.6.0到v16.0.0的版本,都会直接抛出歧义编译错误,提示从
from_type到to_type的转换有两个候选:from_type的转换运算符,以及to_type的转换构造函数; - GCC开启
-pedantic选项后:此时GCC也会输出和Clang一样的歧义错误,明确指出转换路径不唯一。
关于标准符合性和代码本身的问题:
首先可以明确:你的代码没有未定义行为,但它确实触发了C++标准中明确规定的重载解析歧义场景。
根据C++标准中[over.ics.rank](隐式转换序列优先级排序)的规则,当同时存在两条可行的用户自定义转换路径时:
- 路径一:通过
from_type的operator to_type(),直接把from_type对象转换为to_type; - 路径二:通过
to_type的转换构造函数,把from_type对象作为参数构造出临时的to_type对象
这两条转换路径的优先级是完全相同的——没有哪一条转换序列比另一条更“好”,所以按照标准,编译器必须判定这是歧义,拒绝编译。
而GCC在默认模式下的行为,其实是做了一个非标准的扩展:它默认优先选择了转换构造函数,跳过了歧义检查;但当你开启-pedantic选项后,GCC会切换到严格遵循C++标准的模式,这时就会正确地报告这个歧义错误。
总结一下:
- Clang的行为从始至终都是完全符合C++标准的;
- GCC默认模式下的行为不符合标准,但开启
-pedantic选项后就会和标准对齐; - 你的代码本身没有问题,只是刚好触发了标准中规定的重载解析歧义情况。
备注:内容来源于stack exchange,提问作者hmIto
相关产品推荐
相关产品推荐

