假設有一個接收universal references的模板函數(shù)foo,定義如下:
template<typename T>void foo(T&& t) { cout << "foo(T&& t)" << endl; }
如果想對某些類型做特殊處理,寫一個重載版本的foo,比如想對float類型做特殊處理,就寫一個接收float類型的foo:
void foo(float n) { cout << "foo(float n)" << endl; }
這樣,如果我們寫下 foo(1.0) 時,理論上應該輸出"foo(float n)",而實際上輸出結果為"foo(T&& t)"。為什么呢?因為“Functions taking universal reference are the greediest functions in C++”,也就是說universal reference的函數(shù)能準確匹配幾乎所有的類型。當我們調用foo(1.0)時,1.0被推導為double類型,如果調用foo(float n),就需要做narrow conversion,所以編譯器會認為foo(T&& t)為更準確的匹配,除非我們寫下foo(1.f)時,才會調用foo(float)。只有在類型完全準確匹配時,才會調用重載版本,否則編譯器會始終認為universal reference版本為準確匹配。
這個問題在類繼承中會更為隱晦,假設有一個名為Base的class,Base有一個接收universal reference的模板構造函數(shù),定義如下: