Я должен был пробиться через это некоторое время назад. В моем случае конкретные требования требовали, чтобы два элемента сравнивались одинаково только тогда, когда они на самом деле были одного и того же точного типа. То есть вы хотите получить положительное совпадение только при сравнении яблок с яблоками, но на самом производном уровне (золотые яблоки с золотыми яблоками, а не с королевскими праздничными яблоками.
class base {
public:
virtual bool compare( base const & rhs ) = 0;
};
class derived : public base {
public:
virtual bool compare( base const & rhs ) {
if ( typeid(*this) != typeid(rhs) ) return false;
return *this == static_cast<derived const &>(rhs);
}
};
bool operator==( derived const & lhs, derived const & rhs );
Обратите внимание, что в итоге мы использовали typeid
+ static_cast
вместо более распространенной идиомы динамических приведений, чтобы заставить оба типа быть абсолютно одинаковыми. Если бы мы использовали dynamic_cast
, то симметрия могла бы нарушиться и:
class rederived : public derived {
public:
virtual bool compare( base const & rhs ) {
rederived const * p = dynamic_cast<rederived const *>(&rhs);
return p && *this == *p;
}
};
void test() {
derived d;
rederived rd;
d.compare( rd ); // compare if derived subobject is equal, possibly true
rd.compare( d ); // always false, d cannot be dyncamically casted to rederived
}
Опять же, это просто из-за наших конкретных ограничений, которые требовали одинакового типа для обоих объектов. Если вы просто хотите проверить, являются ли они «совместимыми» на одном уровне иерархии (что само по себе является асимметричной операцией, так как левая часть определяет, на каком уровне иерархии вы хотите выполнить сравнение).