重载决议:含模板替换与类型转换的重载为何存在歧义?
C++重载函数调用歧义问题解析
先看你给出的代码:
void foo(int, float){ // 1 std::cout << "1\n"; } template <typename T> void foo(T, int){} // 2 int main() { foo(3.4f, 4.5f); // 此处调用歧义 }
要搞懂这个歧义的根源,得拆解C++重载决议的关键逻辑:
第一步:生成所有可行的候选函数
调用foo(3.4f, 4.5f)时,编译器会找出所有能匹配的函数:
- 普通函数
foo(int, float):第一个实参3.4f(float类型)需要转换为int,第二个实参4.5f直接匹配float参数,属于1次标准转换+1次精确匹配。 - 模板实例化出的
foo(float, int):编译器会自动推导模板参数T为float,得到这个实例。此时第一个实参3.4f精确匹配float参数,第二个实参4.5f需要转换为int,属于1次精确匹配+1次标准转换。
第二步:对比候选函数的优先级
C++里判断哪个候选函数更合适,是挨个参数对比转换序列的优劣:
- 对于第一个参数:模板实例的版本是精确匹配,比普通函数的标准转换更优;
- 对于第二个参数:普通函数是精确匹配,比模板实例的标准转换更优。
这种情况下,没有哪个函数的所有参数转换都优于另一个,编译器无法判定优先级,最终报调用歧义。
你之前误以为“第二个需要模板替换加类型转换”所以优先级更低,但实际上模板实例化后的函数和普通函数平等参与重载决议,而且这里两者的转换序列各有优劣,没有绝对的优先级,才导致了歧义。
内容的提问来源于stack exchange,提问作者user3882729
相关产品推荐
相关产品推荐

