C++重载决议中实参值类别的作用环节及规则疑问
重载决议中值类别的作用环节说明
首先明确核心结论:你看到的6级匹配优先级是隐式转换序列(ICS)的粗粒度跨等级排序,值类别对候选选择的影响属于同匹配等级下的细粒度决胜规则,完全归属于重载决议的范畴,没有出现在粗排序列表中,是因为它只在所有剩余候选的转换序列处于同一粗粒度等级时才会生效,不参与跨等级的优先级比较。
先理清重载决议的分层判定逻辑
重载决议不是只靠那6个等级一次性选出结果,而是分层筛选淘汰:
- 第一层:可行候选筛选
不满足形参实参基本绑定规则的候选会被直接淘汰,根本没有参与后续等级排序的资格。值类别在这一层就会发挥第一重作用:- 非const左值引用(
T&)无法绑定到右值实参 - 右值引用(
T&&、const T&&)无法绑定到左值实参
比如传入右值类型的X时,形参为X&的候选会直接被排除,不会进入后续匹配等级判定。
- 非const左值引用(
- 第二层:粗粒度转换等级排序
对剩下的可行候选,逐个计算每个实参到对应形参的转换等级,就是你在书里看到的排序:完美匹配 > 微调匹配 > 提升匹配 > 标准转换匹配 > 用户自定义转换匹配 > 省略号匹配。只要有一个候选存在某实参的转换等级比其他候选差,该候选直接淘汰。
你提到的X、X&、const X&、X&&、const X&&都能对应X类型实参达到完美匹配等级,指的就是这一层的判定结果——它们都过了粗筛,属于同一等级的候选。 - 第三层:同等级细粒度决胜
当多个候选通过前两层筛选,所有实参的转换粗等级完全一致时,就会触发细粒度决胜规则,值类别对引用绑定优先级的影响就属于这一层的判定逻辑。
同属完美匹配时的引用绑定优先级规则
针对完美匹配等级下的不同形参,结合实参的值类别、cv限定属性,优先级从高到低排序如下:
- 无额外cv限定、和实参值类别完全匹配的引用绑定:
- 左值实参优先匹配
T& - 右值实参优先匹配
T&& - const属性的左值/右值实参优先匹配
const T&/const T&&
这类绑定不需要给引用添加额外const限定,也不需要对实参做拷贝/移动,是最紧密的绑定。
- 左值实参优先匹配
- 需要添加cv限定的引用绑定:比如非const左值实参匹配
const T&、非const右值实参匹配const T&/const T&&,这类绑定虽然属于完美匹配,但因为需要额外加const限定,优先级低于上一类。 - 按值传参的完美匹配:按值传参需要调用拷贝/移动构造函数生成形参对象,即使转换等级属于完美匹配,优先级也低于所有符合绑定规则的引用形参。
可以用一段简单的代码验证这个规则:
struct X {}; void f(X&) {} // 版本1:非const左值引用 void f(const X&) {} // 版本2:const左值引用 void f(X&&) {} // 版本3:非const右值引用 void f(const X&&) {} // 版本4:const右值引用 void f(X) {} // 版本5:按值传参 int main() { X x; f(x); // 左值实参,优先选版本1 const X cx; f(cx); // const左值实参,优先选版本2 f(X()); // 非const右值实参,优先选版本3 const X get_cx(); f(get_cx()); // const右值实参,优先选版本4 }
补充说明
你提到的「按值传参的形参顶层const不属于函数签名」的理解是正确的:void f(X)和void f(const X)是完全相同的函数签名,无法重载。书中完美匹配条目里提到的「可额外添加const/volatile限定符」,对按值传参场景指的是判定匹配时会忽略实参本身的顶层cv限定;对引用传参场景,指的是允许给引用添加底层cv限定完成绑定,这部分的匹配等级依然属于完美匹配。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

