Ich würde die Klasse als nicht kopierbar in Signatur behandeln, wenn die Kopie ausreichend teuer ist. Semantisch gesehen sind Dinge nur dann kopierbar, wenn man sie haben will, und eine teure Kopie ist ein guter Grund, sich für "nein, nicht kopierbar" zu entscheiden.
Die Fähigkeit, etwas zu kopieren, bedeutet nicht, dass es in einem kopierbaren Typ implementiert werden muss. Der Implementierer dieses Typs entscheidet, ob er semantisch kopierbar sein soll.
Ich würde nicht die Operation nennen, die eine teure Kopie "Kopie" produziert, sondern eher "klonen" oder "duplizieren".
Für einen Weg, dies tun könnte:
#include <utility>
template<typename T>
struct DoCopy {
T const& t;
DoCopy(T const& t_):t(t_) {}
};
template<typename T>
DoCopy<T> do_copy(T const& t) {
return t;
}
struct Foo {
struct ExpensiveToCopy {
int _[100000000];
};
ExpensiveToCopy* data;
Foo():data(new ExpensiveToCopy()) {}
~Foo(){ delete data; }
Foo(Foo&& o):data(o.data) { o.data = nullptr; }
Foo& operator=(Foo&& o) { data=o.data; o.data=nullptr; return *this; }
Foo& operator=(DoCopy<Foo> o) {
delete data;
if (o.t.data) {
data=new ExpensiveToCopy(*o.t.data);
} else {
data=new ExpensiveToCopy();
}
return *this;
}
Foo(DoCopy<Foo> cp):data(cp.t.data?new ExpensiveToCopy(*cp.t.data):new ExpensiveToCopy()) {};
};
int main() {
Foo one;
// Foo two = one; // illegal
Foo three = std::move(one); // legal
Foo four;
Foo five = do_copy(three);
four = std::move(three);
five = do_copy(four);
}
Diese auf die Art und Weise ein wenig ähnlich ist Ihnen std::move
wie Semantik vor der Existenz von rvalue Referenzen, mit ähnlichen Nachteilen auf solche Techniken geschrieben haben könnte, dass nämlich Die Sprache selbst hat keine Ahnung, was für Spielereien du bist.
Es hat den Vorteil, dass die Syntax der oben do_copy
auf die Syntax von std::move
ähnlich ist, und es erlaubt Ihnen traditionelle Ausdrücke zu verwenden, ohne eine Kopie eines anderen Variablen usw.
triviale Instanzen
Foo
dann konstruieren zu schaffen, die
Wenn die Situationen, in denen wir sie als kopierbar behandeln möchten, üblich sind (wenn sie vermieden werden sollen), schreibe ich einen Copy-Wrapper um die Klasse, die über die duplicate
-Methode Bescheid weiß.
Ich stelle mir vor, das Problem mit einer 'copy'-Member-Funktion ist, dass es den gesamten Template-Code bricht, der den Zuweisungsoperator verwendet. – Pubby