This:
Derived& operator=(Derived copy)
не объявляет оператор присваивания копии для базового класса (у него неправильная подпись).Поэтому сгенерированный по умолчанию оператор присваивания в Foo
не будет использовать этот оператор.
Запомните 12.8:
Объявленный пользователем оператор присваивания копии X :: operator = не являетсястатическая не шаблонная функция-член класса X с ровно одним параметром типа X, X &, const X &, volatile X & или const volatile X &.) [Примечание: перегруженный оператор присваивания должен быть объявлен как имеющий только один параметр;см. 13.5.3.] [Примечание: для класса может быть объявлено более одной формы оператора копирования.] [Примечание: если класс X имеет только оператор присваивания копии с параметром типа X &, выражение типа const X не может быть присвоено объекту типа X.
EDIT не делайте этого (понимаете почему?):
Вы можете сделать:
template<typename Derived>
struct copy_and_swap
{
void operator=(const copy_and_swap& copy)
{
Derived copy(static_cast<const Derived&>(copy));
copy.swap(static_cast<Derived&>(*this));
}
};
, но вы потеряете потенциальную оптимизацию разрешения копирования.
Действительно, это будет назначать дважды члены производных классов: один раз через copy_and_swap<Derived>
оператор присваивания и один раз через оператор присваивания производного класса.Чтобы исправить ситуацию, вы должны сделать (и не забудьте сделать ):
struct Foo : copy_and_swap<Foo>
{
Foo& operator=(const Foo& x)
{
static_cast<copy_and_swap<Foo>&>(*this) = x;
return *this;
}
private:
// Some stateful members here
}
Мораль этой истории: не пишите класс CRTPдля копирования и обмена идиома .