2014-12-03 11 views
7

Supponiamo la seguente:Specializzazioni di funzioni template esplicite con overload: Perché dovresti farlo?

template <typename T> void foo (T*); // #1 
template <typename T> void foo (T); // #2 
template <> void foo (int*);   // #3 

Quando si introduce una specializzazione esplicita di un modello base che ha anche sovraccarichi, la specializzazione non è considerato durante la risoluzione di sovraccarico di progettazione. Lo capisco.

Ma, dato che potrei rendere # 3 un sovraccarico non di modello e sarebbe quindi considerato per la risoluzione di sovraccarico, perché dovrei comunque voler farlo come ho fatto sopra? Esiste un caso d'uso valido per la configurazione dimostrata sopra? L'unica cosa che posso pensare è che se non si è basata sulla deduzione del tipo di modello, non è stato possibile utilizzare le funzioni non modello poiché non avrebbero accettato la sintassi <> quando le si chiama.

BTW Ho solo rivisto le regole per C++ 03. Non sono sicuro se/come C++ 11 cambi queste regole/comportamenti.

+4

lettura obbligatoria: [GotW # 49 - Template Specialization and Overloading] (http://www.gotw.ca/gotw/049.htm) - TL; DR Non farlo. – sehe

+1

Questo NON è un duplicato. Ti sto chiedendo quando * useresti * le specializzazioni di funzioni esplicite in congiunzione con l'overloading. O, se non dovrebbe essere fatto. Le risposte della domanda collegata NON rispondono a questa domanda. –

+2

Forse c'è un codice non basato sul modello nel tuo codice che accetta un * int. Aggiungere la specializzazione del modello significa che potresti essere esplicito e usare pippo (&i); – cppguy

risposta

1

Fondamentalmente, preferisco la specializzazione per evitare il principio della sorpresa minima. Si desidera consentire alle funzioni di essere chiamate esplicitamente o non esplicitamente per supportare l'utilizzo nella più ampia quantità di codice possibile ... e quando esplicitamente istanziato, dovrebbe comportarsi allo stesso modo di quando non lo era.

La seguente funzione di modello è un esempio di come si desidera selezionare in modo esplicito quale funzione si desidera chiamare (nonostante tutti i 3 utilizzino lo stesso argomento).

template <typename T> void foo (T*){std::cout << 1 << std::endl;} // #1 
template <typename T> void foo (T){std::cout << 2 << std::endl;} // #2 
template <> void foo<int> (int* x){std::cout << 3 << std::endl;} // #3 
//void foo (int*){std::cout << 3 << std::endl;}   // #3 

template <typename T> 
void bar(void* x) { 
    foo<T>(reinterpret_cast<T*>(x)); 
    foo<T*>(reinterpret_cast<T*>(x)); 
    foo(reinterpret_cast<T*>(x)); 
} 


int main() 
{ 
    cout << "Hello World" << endl; 
    bar<int>(NULL); 
    return 0; 
} 

Senza la specializzazione, questo emette 1,2,3 (la chiamata in modo esplicito istanziato è diverso da quello della chiamata sovraccarico), mentre con la specializzazione si ottiene 3,2,3 (l'istanza esplicita è la stessa la chiamata implicita).

1

#3 può essere utilizzato per specializzare le funzioni del modello in un'unità di compilazione senza dover aggiornare altre unità di compilazione.

Diciamo che abbiamo z.cpp che assomiglia a questo:

template <class T> void foo (T*) { puts("1"); } 
template <class T> void foo (T) { puts("2"); } 
template <> void foo (int*) { puts("3"); } 
void foo(int*) { puts("4"); } 

int dummy() { 
    foo((int*)NULL);  
    foo<int>((int*)NULL); 
    foo(4);  
    foo((long*)NULL);  
} 

e y.cpp che assomiglia a questo:

#include <stdio.h> 

template <class T> void foo (T*); 
template <class T> void foo (T); 

int main() { 
    foo((int*)NULL);  
    foo<int>((int*)NULL); 
    foo(4);  
    foo((long*)NULL);  
} 

Le prime righe del principale farà riferimento a #3 e non #4. Ciò significa che siamo in grado di specializzare foo per altri tipi in z.cpp senza dover modificare y.cpp.

Con #4, è necessario aggiornare y.cpp ogni volta che si aggiunge un nuovo sovraccarico.

+0

Sono sicuro al 99% che tale codice viola l'unica regola di definizione e in quanto tale è un comportamento non definito –

+0

@MarkB - Perché? Le definizioni sono solo in 'z .cpp'. – tohava

Problemi correlati