Your template is declared as
template <typename Cat> bool operator==(const Copy<Cat>& copy, const Cat& e)
This does not match redCopy == Red() , because Red() is of type Red , so the compiler outputs Red as the type of the second argument, i.e. Cat = Red , but then it expects the type of the first argument Copy<Red> , which is not ( redCopy type Copy<Apple> ).
What you really want to express is something like
template <typename Cat> bool operator==(const Copy<Cat>& copy, const something-that-derives-from-Cat& e)
The easiest way to do this is to add a second template parameter:
template <typename Cat, typename DerivedFromCat> bool operator==(const Copy<Cat>& copy, const DerivedFromCat& e)
Of course, this prevents the compiler from enforcing that DerivedFromCat is actually derived from Cat. If you want this, you can use boost::enable_if :
template <typename Cat, typename DerivedFromCat> typename enable_if<is_base_of<Cat, DerivedFromCat>, bool>::type operator==(const Copy<Cat>&, const DerivedFromCat& e)
But that might be a little redundant ...
source share