如果我们在代码中使用万能引用型别作为函数重载的一个特征标,这样在我们使用该重载函数时,实际调用的函数可能与我们期望不符:
示例代码如下:
#include <memory> #include <iostream> #include <set> using namespace std; //万能引用型别重载 template <class T> void MaKeZiYuan(T&& t) { cout << "MaKeZiYuan(T&& t)" << endl; }; //参数为int void MaKeZiYuan(int t) { cout << "MaKeZiYuan(int t)" << endl;; }; int main() { MaKeZiYuan("123"); //参数为char*,匹配万能引用型别 MaKeZiYuan(456); //参数为整型常量(int),匹配int型别 int j = 456; MaKeZiYuan(j); //参数为int,匹配int型别 short i = 1; MaKeZiYuan(i); //参数为short,匹配万能引用型别 long k = 1; MaKeZiYuan(k); //参数为long,匹配万能引用型别 system("pause"); }
执行结果如下:
前三个调用我们都能理解,但是最后两个为什么匹配到了万能引用呢?因为按照普适的重载决议规则,精确匹配优先于提升或窄化后匹配,所以才会调用到万能引用型别的重载。很明显这不符合我们的预期。
这样的问题同样存在于我们类的构造函数中,如果使用万能引用作为构造函数的模板,那么你将很难真正调用到其他构造函数。
当然,问题也很好解决,只需要将实参与欲调用的函数的形参完全一致,这样就可以调用到你期望的函数了,因为即使万能引用型别函数也可以完美匹配你的实参,但是按照普适的重载决议另一条规则,当一个模板实例化函数与一个非模板实例化函数具有相等的匹配程度时,优先使用非模板函数作为重载函数。
至此,我们应该形成一个潜意思:形参时万能引用的函数时最贪婪的,它会在具现的过程中,和几乎任何实参型别都会产生精确匹配,不到万不得已,不要使用。