Дилемма реализации реляционного оператора - PullRequest
4 голосов
/ 23 марта 2009

Я нахожусь в процессе разработки нескольких классов, которые должны поддерживать операторы !=, >, <= и >=. Эти операторы будут реализованы в терминах операторов == и <.

На этом этапе мне нужно сделать выбор между наследованием¹ и принуждением своих потребителей использовать 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 ]

5 голосов
/ 23 марта 2009

Рассматривали ли вы использование boost , и чтобы ваш класс наследовал от boost::less_than_comparable<T> и boost::equality_comparable<T>? Это сродни вашему первому предложению, с некоторыми плюсами и минусами. Плюсы: избегает дублирования кода; Минусы: создает зависимость от наддува.

Так как boost - очень распространенная библиотека C ++ (если вы ее еще не используете, вам следует серьезно подумать о том, чтобы начать ее использовать), коэффициент использования неактивен.

1 голос
/ 23 марта 2009

Я думаю, std::rel_ops довольно хорошо, но сначала нужно рассмотреть одну вещь: std::rel_ops предоставляет операторы в качестве шаблонных функций, которые принимают два параметра одного типа. Поскольку большинство преобразований (включая, например, арифметические преобразования и определяемые пользователем преобразования) не выполняются, когда происходит выведение аргументов шаблона, это означает, что вы не сможете использовать ни один из этих дополнительных операторов (например, !=) с такими преобразованиями.

например. если у вас есть класс MyInt, который пытается вести себя как обычное целое число, вы можете написать функции / конструкторы преобразования или шаблонные операторы, чтобы вы могли выполнить

MyInt x, y;

x < 5;
9 == x;

Однако

x > 5;
30 <= x;

не будет работать (с std::rel_ops), поскольку два аргумента имеют разные типы, поэтому вывод аргументов шаблона завершится неудачей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...