Я бы рассматривал класс как не копируемый в подписи, если копирование достаточно дорогое. Семантически вещи можно копировать только в том случае, если вы хотите, чтобы они были копируемыми, а дорогая копия - достойный повод принять решение «нет, копировать нельзя».
Возможность чего-либо копировать не означает, что это нужно реализовать в копируемом типе. Разработчик этого типа должен решить, следует ли его семантически копировать.
Я бы не назвал операцию, которая произвела дорогостоящую копию, «копией», а скорее «клонированием» или «дубликатом».
Например, вы могли бы сделать это:
#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);
}
Это в некоторой степени похоже на то, как вы могли написать std::move
подобную семантику до существования ссылок на rvalue, с теми же недостатками, что и у таких методов, а именно: сам язык не знает, какие махинации вы затеваете.
Его преимущество состоит в том, что синтаксис приведенного выше do_copy
аналогичен синтаксису std::move
и позволяет использовать традиционные выражения без необходимости создавать тривиальные экземпляры Foo
, а затем создавать копию другой переменной и т. Д.
Если ситуации, когда мы хотим рассматривать его как копируемый, обычны (если этого следует избегать), я бы написал обертку для копирования вокруг класса, который знает о методе duplicate
.
person
Yakk - Adam Nevraumont
schedule
06.04.2013
copy
состоит в том, что она нарушает весь код шаблона, который использует оператор присваивания. - person Pubby   schedule 06.04.2013