>假设我们有以下代码片段:
class A
{
public:
virtual bool operator< (const A &rhs) const;
};
class B: public A;
class C: public A;
我希望比较取决于左侧和右侧的实际类型,例如:
x < y == true if type(x) == B and type(y) == C
x < y == false if type(x) == C and type(y) == B
情况可能更复杂,派生类比两个多得多。当然,operator<
必须是一个虚拟功能。有没有一种优雅的写法?
///
/// goal: provide partial ordering of objects derived from A on the basis
/// only of class type.
/// constraint: ordering specified by us
///
#include <vector>
#include <typeindex>
#include <algorithm>
#include <iostream>
class A
{
public:
virtual bool operator< (const A &rhs) const = 0;
static const std::vector<std::type_index>& ordering();
};
template<class T> struct impl_A : public A
{
bool operator< (const A &rhs) const override
{
auto& o = ordering();
auto first = std::begin(o);
auto last = std::end(o);
auto il = std::find(first, last, typeid(T));
auto ir = std::find(first, last, typeid(rhs));
return il < ir;
}
};
class B: public impl_A<B> {};
class C: public impl_A<C> {};
const std::vector<std::type_index>& A::ordering()
{
// specify fording of types explicitly
static const std::vector<std::type_index> _ordering { typeid(B), typeid(C) };
return _ordering;
}
void test(const A& l, const A& r)
{
if (l < r) {
std::cout << typeid(l).name() << " is less than " << typeid(r).name() << std::endl;
}
else {
std::cout << typeid(l).name() << " is not less than " << typeid(r).name() << std::endl;
}
}
int main()
{
test(B(), C());
test(B(), B());
test(C(), B());
test(C(), C());
}
示例输出(喇叭):
1B is less than 1C
1B is not less than 1B
1C is not less than 1B
1C is not less than 1C
好!但是(我的问题不够精确),当 x 和 y 共享相同的类型(例如 B)时,x
示例结果:
1 is less than "hello" 0 is less than 1 1 is not less than 0 0 is not less than 0 "hello" is not less than 1 "goodbye" is less than "hello" "goodbye" is not less than "goodbye" "hello" is not less than "goodbye"
我看到的唯一解决方案是不要将operator<
函数作为虚拟成员函数,而是作为一组重载的非成员函数:一个"默认"函数,它将两个对A
的引用作为参数,然后在特殊情况下各重载一个。