2014-06-09 17 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);来强制执行错误,这将向您显示不可能的转换。