0

我有一個情況下查找和重載解析行爲不同:重載解析,名稱查找和函數指針

  • 用戶定義的類VS內置類型VS的std :: string
  • 直接調用VS函數指針調用

我找不出什麼確切的標準的部分證明這些迪菲分配辦法。

考慮以下C++ 11代碼:

#include <iostream> 
#include <string> 

using namespace std; 

struct Test1 {}; 
struct Test2 {}; 

template<typename T> 
int f(T t) { return 0; } 

int f(Test1 t) { return 10; } 
int f(int y) { return 20; } 

template<typename T> 
int use1() { return f(T()); } 

template<typename T> 
int use2() { auto fp = static_cast<int(*)(T)>(&f); return (*fp)(T()); } 

int f(Test2 t) { return 30; } 
int f(string s) { return 40; } 
int f(double y) { return 50; } 

int main() { 
    cout << "use1<float>: " << use1<float>() << endl; 
    cout << "use1<Test1>: " << use1<Test1>() << endl; 
    cout << "use1<int>: " << use1<int>() << endl; 
    cout << "use1<Test2>: " << use1<Test2>() << endl; 
    cout << "use1<string>: " << use1<string>() << endl; 
    cout << "use1<double>: " << use1<double>() << endl; 
    cout << endl; 
    cout << "use2<float>: " << use2<float>() << endl; 
    cout << "use2<Test1>: " << use2<Test1>() << endl; 
    cout << "use2<int>: " << use2<int>() << endl; 
    cout << "use2<Test2>: " << use2<Test2>() << endl; 
    cout << "use2<string>: " << use2<string>() << endl; 
    cout << "use2<double>: " << use2<double>() << endl; 
    return 0; 
} 

輸出是(相同使用g ++ 6.3和鐺++ 5.0.0主幹):

use1<float>: 0 
use1<Test1>: 10 
use1<int>: 20 
use1<Test2>: 30 
use1<string>: 0 
use1<double>: 0 

use2<float>: 0 
use2<Test1>: 10 
use2<int>: 20 
use2<Test2>: 0 
use2<string>: 0 
use2<double>: 0 

問題:

  1. 爲什麼use1<string>use1<Test2>不同?兩種類型都被聲明爲「頂部」,兩個f()重載都在底部聲明。
  2. 爲什麼use1<Test2>use1<double>不同?相應的f()重載在相鄰的行上,對於內置類型有沒有什麼特別的處理?
  3. 爲什麼use1<Test2>use2<Test2>不同? use2中的函數指針的類型似乎與use1中的調用上下文相匹配。

回答

0

兩階段名稱查找。在定義use1的位置,通過正常查找可以看到三個過載f。在實例化的時候,可能會發現更多的重載 - 但只能通過依賴於參數的查找。 Test2位於全局命名空間中,因此f(Test2)被ADL找到;而string在命名空間std中,所以f(string)(顯然,它不在命名空間std中)未被ADL找到。 double沒有關聯的命名空間,所以ADL根本不踢。

use2,f不是一個從屬名稱,所以第二階段查找根本就不執行 - 只考慮在定義點可見的重載。

+0

謝謝!關於use2:有沒有一種方法在使用2 來獲得一個函數指針,該指針包含與在使用中解析的f()完全相同的過載地址1 ? – salmin

+0

我想不出有什麼辦法「依賴」一個名字。該標準僅設想第二個查找階段,該名稱用於直接函數調用「name(some_args)」中,而不是其他需要執行重載解析的情況。 –