为何模板成员operator<<会优先于友元非模板operator<<被选中?
为何模板成员operator<<会优先于友元非模板operator<<被选中?
这个问题其实是C++重载决议规则里的匹配优先级在搞鬼,咱们一步步拆解来看:
首先看代码里的两个候选函数:
- Builder类里的模板成员operator<<:它是个转发引用模板(
auto&& t),当你传入X类型的左值x时,会被推导成Builder& operator<<(X&),然后调用append(t)。 - X类里的友元非模板operator<<:它的参数是
Builder&和X const&,专门处理X的const左值(当然普通左值也能绑定,但匹配度稍弱)。
接下来看编译器怎么选:
当你写p << x的时候,编译器会先查找Builder的成员函数(包括模板),然后通过ADL(依赖于参数的查找)找到X的友元函数。现在两个候选都符合调用要求,但编译器要挑匹配度最高的那个:
- 第一个参数都是
Builder&,两者匹配度完全一样。 - 第二个参数,模板版本是
X&,正好和实参x的类型(X的非const左值)完全匹配;而友元版本是X const&,虽然也能绑定x,但属于“把非const左值绑定到const引用”,匹配度比前者低一级。
根据C++重载决议的核心规则——更精确的参数匹配会优先被选中,所以编译器最终选择了模板成员版本,而非友元的非模板版本。
顺带提个小测试点:如果把x改成const X x,那友元版本的X const&就会和实参完全匹配,这时候友元函数的匹配度就会超过模板版本,编译器就会转而选择友元函数了。
备注:内容来源于stack exchange,提问作者Chnossos
相关产品推荐
相关产品推荐

