Есть такое понятие, как «принцип подстановки Барбары Лисков». Если подставить на место User класс Comparator, должно сойтись по типам. Но нет: User умеет сравнивать только с самим собой, а Comparator — с любым Comparator.
Теоретически должно было бы подойти такое (так называемая контравариантность). Но не работает ни в Си++, ни в Яве.
class ComparatorBase
{
public:
virtual ~ComparatorBase() = default;
};
class Comparator : public ComparatorBase {
public:
virtual int compare(Comparator *t)=0;
};
class User : public Comparator{
public:
int compare(ComparatorBase *u) override {
return 1;
}
};
А по возвращаемому значению (если возвращается ссылка/указатель) может быть ковариантность, и она работает и в Си++, и в Яве.
class Father
{
public:
virtual Father& foo();
virtual ~Father() = default;
};
class Son : public Father
{
public:
Son& foo() override;
};
Как обойти. Есть два способа.
Способ 1. Пусть старой Явы.
int User::compare(Comparator *u)
{
auto* v = dynamic_cast<User*>(u);
if (!v)
return false;
return v->name > this->name;
}
Способ 2. Так называемый «странно рекуррентный шаблон».
template <class T>
class Comparator {
public:
virtual int compare(T *t)=0;
virtual ~Comparator() = default;
};
class User : public Comparator<User> {
private:
std::string name;
public:
User(std::string name){this->name=name;}
int compare(User *u);
void showName(){std::cout<<"Name "<<this->name<<std::endl;}
};
int User::compare(User *u)
{
return u->name > this->name;
}