2013-06-06 3 views
10

Ci scusiamo per il titolo troppo ambiguo. (A causa della mancanza della mia abilità inglese). Si prega di suggerire un titolo migliore.Perché copiare il costruttore non viene richiamato?

Si prega di considerare il seguente codice.

struct A { 
    typedef std::vector<double> State; 

    // template <class... Args> 
    // A(Args... args) 
    //  : a(args...) 
    // {} 

    template <class... Args> 
    A(Args&&... args) 
      : a(std::forward<Args>(args)...) 
    {} 

    A(const A&) = default; 
    A(A&&) = default; 

    State a; 
}; 

int main(){ 

    A a(3,2); 
    A b = a; // This line triggers an error!! 
} 

Gcc 4.8.0 non è riuscito a compilarlo con il messaggio di errore error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...).

Non riesco a capire perché questo codice sia sbagliato. A mio parere, il compilatore dovrebbe invocare il costruttore di copie nella riga A b = a;.

Tuttavia se sostituisco il costruttore con quello commentato (che prende semplicemente i valori). Compilare. Inoltre, ora non sono necessarie le linee per i costruttori di copia (e spostamento) predefiniti. Cosa succede qui?

risposta

9

In C++ 11 avendo il compilatore dedurre automaticamente i parametri di modello (come si deve fare con un costruttore su modelli) e applicando && al tipo crea un riferimento universale, che corrisponde a qualsiasi tipo con qualsiasi qualifica cv, sia che si tratti di un valore di lvalue o di un valore di riferimento.

Quindi nel tuo caso si sta passando in un A, e quindi Args... = A &, Args &&... = A & &&, che è A & grazie alle regole di riferimento-collasso, che è una partita migliore rispetto const A &, dal momento che il compilatore non lo fa aggiungere constity a una variabile non const.

+1

Oh, capisco. Grazie per la chiara spiegazione :) – Sungmin

3

Penso che in questo caso il costruttore di template sia una corrispondenza migliore perché prende un valore non const. se si cambia a-const che avrebbe chiamato il costruttore di copia ...

const A a(3,2); 
A b = a; 
+0

Grazie se aggiungo un altro costruttore di copia 'A (A &) = default'. Compila bene. :) – Sungmin