2014-06-09 18 views
5

ho il seguente codice:modello di sovraccarico oltre puntatore a puntatore

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; 
} 

In qualche modo l'uscita è "Hi" anche se sembra che migliore corrispondenza sarebbe la seconda funzione template. Quando rimuovo const s come qualificatori su B* e B**, ricevo "Ciao" che corrisponde alla seconda funzione di modello. In che modo il compilatore sceglie la funzione da chiamare in questo caso? Grazie!

risposta

1

Le altre risposte correttamente notano che non esiste alcuna conversione implicita da T** a const T** e quindi uno dei sovraccarichi non è affatto praticabile. Spiegherò perché questa conversione non è consentita. In realtà è scritto come un esempio nello standard. Per citare il paragrafo 4.4,

[Nota: se un programma potrebbe assegnare un puntatore di tipo T ** a un puntatore di tipo const T ** (vale a dire, se la linea # 1 di seguito sono stati autorizzati), un il programma potrebbe inavvertitamente modificare un oggetto const (come avviene sulla riga 2). Per esempio,

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

Dato che non v'è alcuna conversione da T** al T const** il secondo non è una corrispondenza affatto (non v'è tale conversione perché consentirebbe non const accesso a un oggetto const). C'è una conversione da T** a T* const*, tuttavia. Pertanto, il sovraccarico corrispondente è l'unico valido e utilizzato.

3

&c è un TestClass** che può essere promosso a TestClass* const * ma non a const TestClass**.

È possibile forzare l'errore utilizzando esplicitamente test<int, TestClass>(a, &c); che mostrerà la conversione impossibile.