关系运算符实现困境

时间:2009-03-22 23:04:07

标签: c++

我正在设计几个需要支持运算符!=><=>=的类。这些运算符将根据运算符==<实现。

在这个阶段,我需要在继承¹和迫使我的消费者“手动”使用std::rel_ops²之间做出选择。

[1]继承(可能的实现):

template<class T> class RelationalOperatorsImpl
{
    protected:
    RelationalOperatorsImpl() {}
    ~RelationalOperatorsImpl() {}

    friend bool operator!=(const T& lhs, const T& rhs) {return !(lhs == rhs);}
    friend bool operator>(const T& lhs, const T& rhs) {return (rhs < lhs);}
    friend bool operator<=(const T& lhs, const T& rhs) {return !(rhs < lhs);}
    friend bool operator>=(const T& lhs, const T& rhs) {return !(lhs < rhs);}
};

template<typename T> class Foo : RelationalOperatorsImpl< Foo<T> >
{
    public:
    explicit Foo(const T& value) : m_Value(value) {}

    friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);}
    friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);}

    private:
    T m_Value;
};

[2] std::rel_ops胶水:

template<typename T> class Foo
{
    public:
    explicit Foo(const T& value) : m_Value(value) {}

    friend bool operator==(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value == rhs.m_Value);}
    friend bool operator<(const Foo& lhs, const Foo& rhs) {return (lhs.m_Value < rhs.m_Value);}

    private:
    T m_Value;
};

void Consumer()
{
    using namespace std::rel_ops;

    //Operators !=, >, >=, and <= will be instantiated for Foo<T> (in this case) on demand.
}

我基本上试图避免代码重复。关于哪种方法“感觉”更好的想法?

2 个答案:

答案 0 :(得分:5)

您是否考虑过使用boost,并让您的班级继承自boost::less_than_comparable<T>boost::equality_comparable<T>?它类似于你的第一个建议,有一些优点和缺点。优点:避免代码重复;缺点:创建对boost的依赖。

由于boost是一个非常常见的C ++库(如果你还没有使用它,你应该认真考虑开始使用它),con因子会变暗。

答案 1 :(得分:1)

我认为std::rel_ops非常好,但首先要考虑的一件事:std::rel_ops提供运算符作为模板函数,接受两个相同类型的参数。由于大多数转换(包括例如算术促销和用户定义的转换)在模板参数推断发生时不会执行,这意味着您将无法使用任何这些额外的运算符(例如!=)进行此类转换。

E.g。如果你有一个类MyInt试图表现得像一个常规整数,你可能已经编写了转换函数/构造函数或模板化运算符,以便你可以这样做

MyInt x, y;

x < 5;
9 == x;

然而,

x > 5;
30 <= x;

将不起作用(使用std::rel_ops),因为这两个参数的类型不同,因此模板参数推断将失败。