为何function<void(string)>与function<string(string)>重载参数存在歧义?
为什么std::function重载会出现匹配歧义,而显式构造可以解决?
核心原因:std::function的兼容性与隐式转换的等价性
当你传入printNonVoid(返回string的函数指针)到call的重载时,编译器需要判断它能隐式转换成哪个std::function类型:
function<VoidType>(即function<void(string)>):std::function允许构造返回值被忽略的包装器——只要函数参数列表匹配,无论返回值是什么,都能构造出该类型的std::function(调用时会自动丢弃返回值)。function<NonVoidType>(即function<string(string)>):这是与printNonVoid签名完全匹配的std::function类型。
这两个转换都属于用户定义转换(通过std::function的模板构造函数完成),在C++重载决议规则中,它们的转换优先级完全相同——编译器无法判定哪个转换“更优”,因此会抛出重载匹配歧义错误。
函数指针重载无歧义的对比
当重载参数为函数指针类型时,void(string)*和string(string)*是完全不同的原生类型。printNonVoid的类型是string(string)*,只能匹配对应的重载,无法隐式转换成void(string)*(函数指针的类型转换规则严格,不允许返回值不匹配的隐式转换),因此不会产生歧义。
显式构造为什么能解决问题
当你显式写出function(printNonVoid)时,编译器会直接推导出这个临时对象的类型是function<NonVoidType>(完美匹配printNonVoid的签名),此时调用call时参数类型完全匹配对应重载,相当于帮编译器提前确定了转换目标类型,跳过了二选一的判断。
内容的提问来源于stack exchange,提问作者Yannick Meine
相关产品推荐
相关产品推荐

