2013-05-15 22 views
7

Quando ho due overload di funzione su modelli come questo:funzione template overloading: const * contro const &

template<class T> 
void foo(T const&) 
{ 
    // do something with a const reference 
    cout << "const reference version"; 
} 

template<class T> 
void foo(T const*) 
{ 
    // do something with a const pointer 
    cout << "const pointer version"; 
} 

Perché il compilatore scegliamo la prima versione quando un'istanza con un tipo puntatore non-const?

int* bar; 
foo(bar); // prints "const reference version" 

char const* baz; 
foo(baz); // prints "const pointer version" 
+2

È possibile trovare una buona spiegazione di questo problema sul canale 9: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core -Cpp-3-di-n. Ma fondamentalmente Mark B ha risposto alla tua domanda. – mkaes

risposta

4

Il motivo è perché bar è un puntatore non-const, quindi int* const& è in realtà una partita migliore rispetto int const* perché non ha bisogno di aggiungere const al tipo di puntatore.

Se bar erano const qualificato allora sarebbe una corrispondenza esatta per la versione .

0

template<class T> void foo(T const*) richiede un puntatore const su T. Bene, se era l'unica dichiarazione che avevi, ci sarebbe un errore di compilazione mentre stai cercando di passare un puntatore non const come argomento.

Con template<class T> void foo(T const&) il tipo T dedotto è int* che viene fornito facendo riferimento alla funzione.

2
#include <iostream> 
using namespace std; 
void foo(int const&) { 
    cout << "const reference" << endl; 
} 

void foo(int const*) { 
    cout << "const pointer" << endl; 
} 

int main() { 
    int *hi; 
    foo (hi); //const pointer 
    foo((*hi)); //const reference 
    foo(&(*hi));//const pointer 
} 

L'offerta qui è riferimento e i puntatori sono diversi. Un puntatore è un tipo univoco, dove come riferimento a un valore non è diverso dal valore stesso, o piuttosto, un alias all'oggetto. Ad esempio, questa versione del codice sopra non verrà compilata.

#include <iostream> 
using namespace std; 
void foo(int const&) { 
    cout << "const reference" << endl; 
} 

void foo(int) { 
    cout << "hi there" << endl; 
} 

int main() { 
    int hi; 
    foo(hi); //const reference 
} 

Come le dichiarazioni di foo sono ambigue. Il compilatore non può decidere tra di loro.

+0

grazie per la dimostrazione dell'ambiguità – idefixs

1

È possibile determinare cosa sta succedendo con i tipi di modello utilizzando typeid.

#include <iostream> 
#include <typeinfo> 
using namespace std; 

template<class T> void foo(T const&) { 
    cout << "const reference version T="<< typeid(T).name()<<endl; 
} 

template<class T> void foo(T const*) { 
    cout << "const pointer version T="<<typeid(T).name()<<endl; 
} 

int main() { 
    int* i_ptr=0; 
    foo(i_ptr); 

    const int* ci_ptr=0; 
    foo(ci_ptr);  
} 

This uscite (nota uscita esatta dipenderà dal compilatore)

const reference version T=Pi 
const pointer version T=i 

che dimostra che nel primo caso T = int* e tipo di argomento completo è int* const&, e nel secondo T=int e il pieno il tipo di argomento è int const *.

Problemi correlati