2014-06-09 45 views
5

我有以下代碼:模板超載加上指針的指針

template<class A, class B> 
void test(A& a, const B* b) 
{ std::cout << "hi" << std::endl; } 

template<class A, class B> 
void test(A& a, const B** b) 
{ std::cout << "hello" << std::endl; } 

class TestClass 
{}; 


int main() 
{ 
    int a = 5; 
    TestClass b; 
    TestClass* c = &b; 
    test(a, &c); 
    return 0; 
} 

不知怎的,輸出是「喜」雖然看上去更好的匹配將是第二個模板功能。當我刪除const s作爲B*B**的限定符時,我會得到對應於第二個模板函數的「hello」。在這種情況下,編譯器如何選擇要調用的函數?謝謝!

回答

1

其他答案正確地注意到,沒有從T**const T**的隱式轉換,因此其中一個重載根本不可行。我會解釋爲什麼不允許這種轉換。它實際上是作爲標準書寫的一個例子。引用段落4.4,

[注意:如果一個程序可能類型T **的指針分配給類型爲const T **(即,如果線#1的下方被允許),一個的指針 程序 可能會無意中修改一個const對象(因爲它在#2行完成)。 例如,

int main() { 
    const char c = ’c’; 
    char* pc; 
    const char** pcc = &pc; // #1: not allowed 
    *pcc = &c; 
    *pc = ’C’; // #2: modifies a const object 
} 
3

鑑於沒有轉換從T**T const**第二未匹配在所有(不存在這樣的轉換,因爲它允許非const訪問const對象)。然而,有一個從T**T* const*的轉換。因此,相應的過載是唯一可行和使用的過載。

3

&cTestClass**,其可能被提升爲TestClass* const *而不是const TestClass**

您可以通過明確使用test<int, TestClass>(a, &c);來強制執行錯誤,這將向您顯示不可能的轉換。