12

mia comprensione su C++ implicita costruttore di copia è simile arazionale dietro C++ copia implicita e spostare costruttore?

T(T const& x) : 
    base1(x), base2(x) ... , 
    var1(x.var1), var2(x.var2)... 
{} 

Spostare costruttore, copia & assegnazione mossa segue anche modello simile.

Perché non è stato definito simile al seguente?

T(T const& x) : 
    base1(static_cast<base1 const&>(x)), 
    base2(static_cast<base2 const&>(x)) ... , 
    var1(x.var1), var2(x.var2)... 
{} 

Esempio

ho avuto una classe che aveva implicita copiare/spostare operatore di costruttore/assegnazione, così come alcuni costruttori di conversione. Stavo delegando il lavoro a qualche classe di implementazione.

class common_work //common implementation of many work like classes 
{ 
    common_work(common_work const&) = default; 
    common_work(common_work&&) = default;// ... implicit constructors work for me. 
    //a forwarding constructor which can take many work like objects 
    template<class T, enable_if<work_like<T> > > 
    common_work(T&& x) { ... } 
}; 
class work1 //one of the implementation 
{ 
    work1(work1 const&) = default; 
    work1(work1&&) = default; ... 
    common_work impl_; 
}; 

questo andava bene, come work1 copiare/spostare i costruttori stava chiamando costruttore di copia/spostamento per common_work, e spedizioni costruttore è stato utilizzato da altri costruttori [non mostrati nel codice], che converte da un altro tipo di work.

Quindi ho pensato di ereditare work1 da common_work per EBO e altri motivi. Così la nuova classe work1 sembrava

class work1 : private common_work 
{ 
    work1(work1 const&) = default; 
    work1(work1&&) = default; ... 
}; 

Ma come, work1 è una classe work_like, improvvisamente il costruttore inoltro stava ottenendo una migliore corrispondenza, come il costruttore di copia/spostamento per common_work richiede un static_cast da deriva alla base.

NOTA:

  • C'è un simile tipo di esempio dato da Scott Meyers, dove copia costruzione trigger spedizioni costruttore come costruttore di copia richiede un'aggiunta const, durante l'inoltro costruttore richiede nessuno. Ma penso che questo problema si verifichi a causa di un design di classe errato, mentre il problema qui è dovuto all'argomento passato alla classe base durante la copia/mossa implicita non sono la corrispondenza esatta.
  • Non riesco a scrivere un costruttore/assegnazione di inoltro universale ed eliminare quelli impliciti, poiché le funzioni eliminate partecipano anche alla risoluzione di sovraccarico e causano errori se soddisfatte esattamente.
  • La soluzione attualmente disponibile è di rendere common_work come un CRTP, cioè il tipo di classe derivata passato come argomento del modello e nel costruttore di inoltro filtrarlo come enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >. In caso contrario, devo scrivere manualmente copia/sposta costruttore/assegnazione per work1 e static_cast alle classi di base in modo esplicito, che è bacato, soggetto a errori e rischio di manutenzione.
+0

Forse si potrebbe aggirare questo rafforzando il vincolo SFINAE in modo tale da rifiutare 'T's che sono derivati ​​da' common_work'? –

+0

Questo è quello che faccio al momento. Guarda il terzo punto nella sezione NOTE. Tuttavia, non dovrebbe essere "is_same ", piuttosto "is_same , Derivato>" – abir

+0

OK, mi dispiace. Non ho letto l'ultima nota :) –

risposta

1

Questo problema è stato discusso nella pagina di bugstracker di MSVC++ alcuni anni fa (quindi se non è stato risolto, è un problema noto su MSVC++). Lo Standard dice

  • ... la base o il membro è diretta-inizializzato con la base o di membro di x corrispondente.

ho la prova vari compilatori quando ho letto il bugreport, e tutti loro "magicamente fuso". Lo standard sembra essere tranquillo sui dettagli (anche riguardo alla categoria del valore e ai qualificatori di c/v), e dice semplicemente "con la base corrispondente ... di x", che IMO ha molto più senso se lo si interpreta "con non x, ma con la base corrispondente ... di x" piuttosto che passarlo l'oggetto completo (andrei anche a dire che può solo ha senso in questo modo).

+0

Si noti che le funzioni dei membri speciali esplicitamente predefinite non sono ancora implementate in MSVC (anche se hanno affermato che verranno presto inserite nel RTM 2013). –

Problemi correlati