Moje rozumienie o C++ niejawny kopii konstruktora jest podobna doracjonalne uzasadnienie C++ ukrytego kopiowania i przenoszenia konstruktora?
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
Move konstruktorze, skopiuj & przypisanie ruch następuje również podobny wzór.
Dlaczego nie zdefiniowano go w podobny sposób?
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
Przykład
miałem klasy, który miał ukryte kopiowania/operatora konstruktor/przydziału, jak również niektóre konwersji konstruktorów. Delegowałem pracę do pewnej klasy implementacji.
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_;
};
To dobrze, jak work1
kopii/konstruktory ruch dzwoni konstruktora kopiowania/dla common_work
i przesyłanie konstruktora użyto innych konstruktorów [niepokazane kodu, który przetwarza] z innego rodzaju work
.
Potem pomyślałem o odziedziczeniu work1
z common_work
dla EBO i innych powodów. Tak więc nowy work1
klasa wyglądało
class work1 : private common_work
{
work1(work1 const&) = default;
work1(work1&&) = default; ...
};
Ale jak work1
jest klasą work_like
nagle konstruktor spedycja był coraz lepszy mecz, jako konstruktor kopia/ruch dla common_work
wymaga static_cast
z pochodzącą do bazy.
UWAGA:
- Jest podobny rodzaj przykład podany przez Scott Meyers, gdzie budowa kopia wyzwala spedycja konstruktor jako konstruktora kopii wymaga const Ponadto podczas przesyłania konstruktora wymaga żadnego. Ale myślę, że ten problem powstaje z powodu niewłaściwego projektowania klas, podczas gdy problem tutaj wynika z tego, że argument przekazany do klasy bazowej podczas niejawnego kopiowania/przenoszenia nie jest dokładnie dopasowany.
- Nie mogę zapisać uniwersalnego przekierowania/przypisania i usunąć niejawne, ponieważ usunięte funkcje uczestniczą również w przeciążeniu i powodują błąd, jeśli są dokładnie dopasowane.
- Rozwiązaniem, które obecnie mam, jest utworzenie
common_work
jako CRTP, tj. Wyprowadzony typ klasy przekazany jako argument szablonu, a w konstruktorze przekazującym filtrowanie go jakoenable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
. W przeciwnym razie muszę ręcznie napisać copy/move constructor/assignment dlawork1
istatic_cast
do klas bazowych jawnie, co jest błędne, podatne na błędy i zagrożenie konserwacyjne.
Być może można to obejść, wzmacniając ograniczenie SFINAE, tak aby odrzucił "T", które pochodzą od 'common_work'? –
To właśnie teraz robię. Spójrz na 3 punkt w sekcji UWAGA. Chociaż nie powinno to być 'is_same', raczej 'is_same , Derived>' –
abir
OK, przepraszam. Nie czytałem ostatniej notatki :) –