2015-09-12 21 views
5

Ho una classe template che ha un costruttore di copia template. Il problema è quando istanzio questa classe usando un'altra istanza di questa classe con lo stesso tipo di template, il mio costruttore di copia template non viene chiamato. Perché non corrisponde? Ecco il frammento di codice:Costruttore di copia modello C++ su modello classe

#include <iostream> 

template <typename T> 
class MyTemplateClass 
{ 
    public: 
     MyTemplateClass() 
     { 
      std::cout << "default constructor" << std::endl; 
     } 

     /* 
     MyTemplateClass(const MyTemplateClass<T>& other) 
     { 
      std::cout << "copy constructor" << std::endl; 
     } 
     */ 

     template <typename U> 
     MyTemplateClass(const MyTemplateClass<U>& other) 
     { 
      std::cout << "template copy constructor" << std::endl; 
     } 
}; 

int main() 
{ 
    MyTemplateClass<int> instance; 
    MyTemplateClass<int> instance2(instance); 
    return EXIT_SUCCESS; 
} 

L'uscita è

default constructor 

Ma se scrivo esplicitamente il costruttore di copia di default (decommentando esso), allora l'uscita diventa

default constructor 
copy constructor 

Io davvero non capisco. L'ho provato con il mio compilatore locale (clang-500.2.79) e con this one (gcc 4.9.2) e ho ottenuto lo stesso risultato.

+5

Un modello non è mai (!) Un costruttore di copia! –

+5

Un costruttore di copia non è mai un modello. –

+0

Esiste un costruttore di copie dichiarato implicitamente che è preferito dalla risoluzione di sovraccarico. –

risposta

2

Un costruttore di copie ha il formato X(X&) o (X const&) e verrà fornito dal compilatore se non l'ha dichiarato (o alcune altre condizioni che non sono pertinenti qui). Non hai, così implicitamente abbiamo la seguente serie di candidati:

MyTemplateClass(const MyTemplateClass&); 
template <typename U> MyTemplateClass(const MyTemplateClass<U>&); 

Entrambi sono vitali per

MyTemplateClass<int> instance2(instance); 

Entrambi prendono gli stessi argomenti esatte. Il problema non è che il modello di costruttore di copia non corrisponde a corrisponde a. Il problema è che il costruttore implicito di copia non è un modello di funzione, e i non-modelli sono preferiti alle specializzazioni di modelli quando si tratta di risoluzione di sovraccarico. Da [over.match.best], omettendo i punti elenco non correlati:

Date queste definizioni, una funzione F1 praticabile è definita come una funzione migliore di un'altra funzione vitale F2 se per tutti gli argomenti i, ICS I (F1) non è una sequenza di conversione peggio di ICS i (F2), e poi
- [...]
- F1 non è una funzione di modello di specializzazione e F2 è un modello di specializzazione di funzione, o, in caso contrario,
- [...]

Ecco perché chiama il costruttore di copia implicito (e quindi, esplicito) sul modello di costruttore.

+0

Perché i modelli non sono preferiti per le specializzazioni dei modelli quando si tratta di risoluzione di sovraccarico? È perché nella maggior parte dei casi è la migliore strategia da scegliere? – syntagma

+1

@REACHUS La risposta diretta è perché questa è la regola (aggiunta citazione standard). La regola generale è: scegliere la funzione più specifica possibile. Il non modello è più specifico del modello. – Barry

+0

Serbatoi Ok, il mio errore era pensare che non sarebbe stato generato alcun costruttore di copia. – Jairard

2

Quando non si dispone di un costruttore di copia nel codice, il compilatore lo genererà implicitamente. Perciò, quando si esegue questa riga:

MyTemplateClass<int> instance2(instance); 

un costruttore di copia è realizzazione, anche se ovviamente non il vostro. Penso che i modelli non abbiano niente a che fare con questo.

Per saperne di più su di esso qui: Implicitly-defined copy constructor

-1

penso REACHUS è giusto, il compilatore genera un costruttore di copia di default (come si farebbe con una classe non-template troppo) e preferendo questo sopra il modello in quanto è più specializzato Dovresti rendere privato il tuo normale costruttore di copie, o meglio usare la parola chiave "cancellata" C++ 11 per contrassegnare la funzione come inutilizzabile. EDIT: Questo non si compila, mi dispiace, non ero in grado di testarlo al momento.

+0

Entrambi questi suggerimenti renderebbero impossibile la compilazione del codice, preferendo non chiamare il modello del costruttore. – Barry

+0

@Barry Perché pensi che non sia una buona idea dichiarare un costruttore di copie cancellato in questo caso? – syntagma

+0

@REACHUS Ciò renderebbe la classe non percettibile. Non credo che sia l'obiettivo dell'OP. – Barry

Problemi correlati