C++20函数重载优先级困惑:fct(f,i)调用为何无歧义?
C++20函数重载匹配疑问解析
示例代码
#include <iostream> using namespace std; void fct(int, float) {cout << "Function no 1" << endl;} void fct(int, double) {cout << "Function no 2" << endl;} void fct(float&, int&) {cout << "Function no 3" << endl;} void fct(const float&, const int&) {cout << "Function no 4" << endl;} int main() { int i = 1; int& ri = i; char c = 'A'; float f = 2.f; double d = 3.0; const double& rdC = d; // 疑问调用A fct(f, 1); // 疑问调用B fct(f, i); }
疑问点
调用A:
fct(f, 1);
推理:第一个参数f可匹配函数3和4(完美类型匹配);第二个参数1可匹配函数1、2、4,其中函数4是完美匹配。判断调用函数4,实际结果符合预期。调用B:
fct(f, i);
推理:第一个参数f可匹配函数3和4(完美类型匹配);第二个参数i也可匹配函数3和4(完美类型匹配),因此判断调用存在歧义,但实际结果是匹配函数3,无法理解原因。若假设float&比const float&优先级更高,那调用A应该存在歧义,但实际并非如此。
解析
核心规则:重载决议的引用绑定优先级与参数匹配排序
C++重载决议中,当多个候选函数都能匹配调用时,会通过隐式转换序列的优劣筛选最优匹配,这里的关键是理解非const左值引用和const左值引用的绑定规则,以及参数匹配的整体比较逻辑。
调用A:fct(f, 1);
第二个参数1是右值(字面量),而函数3的第二个参数是int&——非const左值引用只能绑定到可修改的左值,无法绑定右值,因此函数3直接被排除出候选集。此时只有函数4能同时完美匹配两个参数:
f(float左值)可以绑定到const float&1(int右值)可以绑定到const int&
函数1、2的第一个参数是int,f需要隐式转换为int,优先级低于完美匹配的函数4,所以最终调用函数4。
调用B:fct(f, i);
两个参数都是可修改的左值:
f(float左值)既可以绑定到float&(函数3),也可以绑定到const float&(函数4)i(int左值)既可以绑定到int&(函数3),也可以绑定到const int&(函数4)
这里的关键规则是:对于左值参数,绑定到非const左值引用的优先级高于绑定到const左值引用。重载决议会比较所有参数的转换序列,当函数A的每个参数转换序列都不劣于函数B,且至少有一个参数的转换序列更优时,函数A会被选中。
函数3的两个参数绑定都是非const引用,比函数4的const引用绑定更优,因此函数3是更优匹配,不会出现歧义。
为什么调用A没有歧义?
调用A的第二个参数1是右值,无法绑定到函数3的int&参数,函数3直接被排除,自然不会和函数4产生竞争,因此不存在歧义。
内容的提问来源于stack exchange,提问作者TCH
相关产品推荐
相关产品推荐

