This:
Derived& operator=(Derived copy)
doesn't declare a copy assignment operator for the base class (it has the wrong signature). So the default generated assignment operator in Foo
will not use this operator.
Remember 12.8:
A user-declared copy assignment operator X::operator= is a non-static
non-template member function of class X with exactly one parameter of
type X, X&, const X&, volatile X& or const volatile X&.) [Note: an
overloaded assignment operator must be declared to have only one
parameter; see 13.5.3. ] [Note: more than one form of copy assignment
operator may be declared for a class. ] [Note: if a class X only has a
copy assignment operator with a parameter of type X&, an expression of
type const X cannot be assigned to an object of type X.
EDIT don't do this (can you see why ?):
You can do:
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));
}
};
but you lose the potential copy elision optimization.
Indeed, this would assign twice the members of derived classes: once via copy_and_swap<Derived>
assignment operator, and once via the derived class' generated assignment operator. To correct the situation, you'd have to do (and not forget to do):
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
}
The moral of the story: don't write a CRTP class for the copy and swap idiom.
operator=
since you are missing one in yourFoo
class? Maybe you'll have to doFoo::operator=(){return copy_and_swap();}
(pseudocode)? – Issue