2014-12-02 9 views
6

Nel codice seguente un oggetto s della classe S viene utilizzato per inizializzare un oggetto della classe D con un'inizializzazione diretta D d(s);. La funzione di conversione S :: operator D() viene utilizzata per convertire l'oggetto s in un oggetto temporaneo di tipo D. Quindi, gcc e clang elidano entrambi la chiamata esplicita al costruttore di spostamenti D(&&), per spostare questo oggetto temporaneo in d. Vedi live example.gcc e clang entrambi elidano la chiamata al costruttore di movimento nello snippet seguente. È corretto?

#include <iostream> 
struct D; 
struct S{ operator D(); }; 

struct D{ 
    D(){} 
    D(D&&) { std::cout << "move constructor" << '\n'; } 
}; 

S::operator D() { std::cout << "conversion function" << '\n'; return D(); } 

int main() 
{ 
    S s; 
    D d(s); 
} 

sto contestando la correttezza di questa elisione, per i seguenti motivi:

  1. Questo caso è trattato nel primo punto sub-proiettile in §8.5/16 (N3337), che è silenzioso di elisione.

    Se l'inizializzazione inizializzazione diretta, o se non é copia-inizializzazione dove la versione cv-non qualificato del tipo di origine è la stessa classe, o una classe derivata, la classe della destinazione i costruttori sono considerati. I costruttori applicabili vengono enumerati (13.3.1.3) e il migliore viene scelto tramite la risoluzione di sovraccarico (13.3). Il costruttore così selezionato viene chiamato per inizializzare l'oggetto , con l'espressione di inizializzazione o elenco di espressioni come argomento (i) . Se non viene applicato alcun costruttore o se la risoluzione di sovraccarico è ambigua, l'inizializzazione non è corretta.

  2. Si noti che il punto successivo di puntata indica esplicitamente la possibilità di elisione.
  3. La chiamata al costruttore di spostamento è esplicita. Come può essere eliso?

risposta

8

Lo standard C++ ama creare eccezioni alle regole definite in un punto in una posizione completamente diversa.

Le regole di elisione copia/sposta sono specificate in 12.8/31. Ci sono due operazioni di copia/spostamento da eliminare nel codice.

Il primo è semplice: entro operator D, il temporaneo costruito nell'espressione di ritorno viene spostato nel temporaneo che rappresenta il valore di ritorno della funzione. Bullet 3 consente l'elisione di questa mossa.

Il secondo è lo spostamento del valore di ritorno della funzione temporanea sull'oggetto d. Ancora una volta, il proiettile 3 consente l'elisione.

  • quando un oggetto classe temporanea che non è stato legato ad un riferimento (12.2) viene copiato/spostato ad un oggetto di classe con lo stesso tipo cv-qualificato, l'operazione di copia/spostamento può essere omesso da costruire l'oggetto temporaneo direttamente nella destinazione della copia/mossa omessa
Problemi correlati