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 comeenable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
. In caso contrario, devo scrivere manualmente copia/sposta costruttore/assegnazione perwork1
estatic_cast
alle classi di base in modo esplicito, che è bacato, soggetto a errori e rischio di manutenzione.
Forse si potrebbe aggirare questo rafforzando il vincolo SFINAE in modo tale da rifiutare 'T's che sono derivati da' common_work'? –
Questo è quello che faccio al momento. Guarda il terzo punto nella sezione NOTE. Tuttavia, non dovrebbe essere "is_same", piuttosto "is_same , Derivato>" –
abir
OK, mi dispiace. Non ho letto l'ultima nota :) –