防止兄弟结构的平等比较

Ber*_*ard 7 c++ inheritance siblings c++17

为了代码重用的目的,我有许多派生自同一个基础的结构,但我不想要任何形式的多态.

struct B {
    int field;
    void doStuff() {}
    bool operator==(const B& b) {
        return field == b.field;
    }
};

struct D1 : public B {
    D1(int field) : B{field} {}
};
struct D2 : public B {
    D2(int field) : B{field} {}
};
Run Code Online (Sandbox Code Playgroud)

结构D1D2(以及更类似的结构)派生自B共享公共字段和方法,因此我不需要在每个派生类中复制这些字段和方法.

结构B永远不会被实例化; 我只使用D1和的实例D2.此外,D1并且D2根本不应该彼此互动.从本质上讲,我不希望任何多态行为:D1并且D2,出于所有目的,应该充当不相关的结构.

我希望任何D1与其他D1s 相比较的平等,以及任何D2与其他D2s 相比较的平等.由于D1并且D2不包含任何字段,因此在struct中定义相等运算符似乎是合适的B.

但是,(正如预期的那样)我D1和之间进行了以下互动D2:

int main() {
    D1 d1a(1);
    D1 d1b(1);
    D2 d2(1);

    assert(d1a == d1b); // good

    assert(d1a == d2); // oh no, it compiles!
}
Run Code Online (Sandbox Code Playgroud)

我不希望能够D1D2对象进行比较,因为出于所有目的,它们应该表现得与它们无关.

如何在不重复代码的情况下使最后一个断言成为编译错误?分别定义等号操作符D1D2(和所有其他类似结构)将意味着代码的重复,所以我想避免,如果可能的.

MSa*_*ers 7

"结构D1和D2(以及更相似的结构)来自B,以分享共同的领域和方法"

然后做B一个private基类.显然,D1并且D2不应该共享它们的相等运算符,因为这两个运算符采用不同的参数.您当然可以共享部分实现bool B::equal(B const&) const,因为外部用户无法访问.


use*_*342 4

您可以使用CRTPoperator ==仅在对最终类型的基类的引用上定义:

template<typename T>
struct B {
    int field;
    void doStuff() {}
    bool operator==(const B<T>& b) {
        return field == b.field;
    }
};

struct D1 : public B<D1> {
    D1(int field) : B{field} {}
};
struct D2 : public B<D2> {
    D2(int field) : B{field} {}
};
Run Code Online (Sandbox Code Playgroud)

这会导致第一个assert编译,而第二个被拒绝。