C++ says
Because a copy assignment operator is
implicitly declared for a class if not declared by the user, a base class copy assignment operator is always
hidden by the copy assignment operator of a derived class (13.5.3). A using-declaration (7.3.3) that brings
in from a base class an assignment operator with a parameter type that could be that of a copy-assignment
operator for the derived class is not considered an explicit declaration of a copy-assignment operator and
does not suppress the implicit declaration of the derived class copy-assignment operator; the operator introduced by the using-declaration is hidden by the implicitly-declared copy-assignment operator in the
derived class.
The bug in the code is that your base class declares the operator=
to accept a reference of type of the derived class. That won't prevent an implicit public declaration of an operator= for the base. Thus, your derived class and your base class are still assignable. Try changing your noncopyable class into a non-template, which should suffice:
class Uncopyable
{
protected:
Uncopyable() {}
virtual ~Uncopyable() {}
private:
Uncopyable(const Uncopyable &);
Uncopyable & operator=(const Uncopyable&);
};
One more thing i have just figured in that code: Don't make the destructor of Uncopyable virtual. The reason is, no-one (apart from the derived class itself) can call delete on a pointer to Uncopyable (because 1: the destructor is protected, 2: you derive privately). So it's not the concern of Uncopyable to make the destructor of the derived class implicitly virtual. If the derived class needs to have a virtual destructor, put virtual in there instead, and leave Uncopyables' destructor non-virtual.