我试图在我想要放在STL集合容器中的子类中实现严格的弱排序。 STL集使用运算符<以严格的弱顺序排列其元素。在我的情况下,我有一个类型的层次结构,我不太确定如何为派生类型实现这一点。为此,我快速地live demo展示了我不确定的地方。我使用易于使用的std :: tie technique来命令字段。我不确定的领域是我应该如何称呼超级班级。运营商LT;在派生字段上调用std :: tie比较之前。
struct Base {
Base(const int& rIntVal, const std::string& rStrVal)
: mIntVal(rIntVal)
, mStrVal(rStrVal)
{}
inline bool operator<(const Base& rhs) const {
return std::tie(mIntVal, mStrVal) < std::tie(rhs.mIntVal, rhs.mStrVal);
}
private:
int mIntVal;
std::string mStrVal;
};
struct Derived : public Base {
Derived(
const int& rIntVal,
const std::string& rStrVal,
const std::string& rOtherStrVal,
const std::string& rOtherStrVal1)
: Base(rIntVal, rStrVal)
, mOtherStrVal(rOtherStrVal)
, mOtherStrVal1(rOtherStrVal1)
{}
inline bool operator<(const Derived& rhs) const {
// not sure what to do here - this is my best guess???
if( Base::operator<(rhs) ) {
return std::tie(mOtherStrVal, mOtherStrVal1) <
std::tie(rhs.mOtherStrVal, rhs.mOtherStrVal1);
} else {
return false;
}
}
private:
std::string mOtherStrVal;
std::string mOtherStrVal1;
};
答案 0 :(得分:4)
您最好将引用绑定到基类:
bool operator<(const Derived& rhs) const {
return std::tie(static_cast<const Base&>(*this), mOtherStrVal, mOtherStrVal1) <
std::tie(static_cast<const Base&>(rhs), rhs.mOtherStrVal, rhs.mOtherStrVal1);
}
首先按超类字段进行比较,然后再按子类字段进行比较。
答案 1 :(得分:2)
首先,您可以选择让派生字段优先于基础字段,以便首先考虑派生成员,或者可以优先考虑基本字段。要做什么取决于你的课程的含义以及如何分类。
您已经选择首先比较基本字段,这很好,所以我们将使用它。
要成为一个严格的弱排序,你应该只比较基础子对象相等时的派生字段(即两者都不小于另一个)。
如果您有lhs.mIntVal < rhs.mIntVal
,那么使用当前代码应该返回true,而是继续比较派生字段,最后可能会说lhs
不是小于rhs
,即使基类的结果表明它是。
所以为了使结果正确,你需要一些等同于:
的东西bool operator<(const Derived& rhs) const {
if (Base::operator<(rhs))
return true;
else if (rhs.Base::operator<(*this))
return false;
// base parts are equivalent, compare derived parts:
return std::tie(mOtherStrVal, mOtherStrVal1) <
std::tie(rhs.mOtherStrVal, rhs.mOtherStrVal1);
}
这在逻辑上是正确的,但是次优,因为您拨打Base::operator<
两次。您可以通过在关键字表达式中包含基础对象来避免这种情况,如ecatmur所示。