C ++ больше или равно оператору - PullRequest
0 голосов
/ 06 сентября 2018

В C ++ для оператора, большего или равного ("> ="), достаточно, чтобы операторы равных ("=") и больше (">") были перегружены, чтобы иметь функциональность для больше или равно ("> =")? Или мне нужно перегрузить оператор ("> ="), чтобы иметь функциональность для него?

Ответы [ 4 ]

0 голосов
/ 06 сентября 2018

Нет, C ++ не пишет эти операторы для вас.

Если вы думаете, что это отстой, вы правы. Множество способов сделать так, чтобы это сосало меньше, уже сделано. Я расскажу о 4 из них.

Ожидание

В , если вы правильно напишите operator<=> ( 3-way оператор "космического корабля") или =default it тогда для вас будут написаны все <, <=, >=, >, != и ==.

struct bob {
  int x,y;
  auto operator<=>( bob const& )const = default;
};

В приведенном выше bob каждый оператор < == и т. Д. Написан для него на C ++.

Просто напишите их

До вы должны написать все из них, если хотите их все. Это утомительно и подвержено ошибкам.

Использование std::tie и вызов < и т.п. для них немного менее подвержены ошибкам:

struct bob {
  int x, y;
  friend bool operator<( bob const& lhs, bob const& rhs ) {
    return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
  }
};

или даже

struct bob {
  int x, y;
  friend auto as_tie( bob const& b ) { // C++14
    return std::tie(b.x, b.y);
  }
  friend bool operator<( bob const& lhs, bob const& rhs ) {
    return as_tie(lhs) < as_tie(rhs);
  }
};

потому что tuple делает правильное лексографическое сравнение; написание лексографических сравнений без ошибок раздражает.

Метапрограмма вашего обхода

При сравнении строк вы обычно используете strcmp. Возвращает отрицательное число, если меньше, положительное число, если оно больше, и 0, если оно равно. Этот шаблон может быть более эффективным, чем повторное выполнение < или ==.

Создание одной strcmp подобной функции приводит к < ==, и могут быть выполнены другие операции сравнения:

namespace utils {
  template<class D>
  struct use_cmp {
    friend bool operator<( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) < 0;
    }
    friend bool operator>( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) > 0;
    }
    friend bool operator<=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) <= 0;
    }
    friend bool operator>=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) >= 0;
    }
    friend bool operator==( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) == 0;
    }
    friend bool operator!=( use_cmp<D> const& lhs, use_cmp<D> const& rhs ) {
      return cmp( lhs.self(), rhs.self() ) != 0;
    }
  private:
    D const& self() const { return *static_cast<D const*>(this); }
  };
}

Теперь у нас есть тип:

struct bob {
  int x, y;
};

и мы хотим иметь возможность использовать операторы сравнения на нем:

struct bob : utils::use_cmp<bob>
{
  int x, y;
  bob( int x_, int y_ ):x(x_), y(y_) {} // constructor
  friend int cmp( bob const& lhs, bob const& rhs ) {
    if (lhs.x < rhs.x) return -1;
    if (lhs.x > rhs.x) return 1;
    if (lhs.y < rhs.y) return -1;
    if (lhs.y > rhs.y) return 1;
    return 0;
  }
};

и использование магии CRTP bob теперь имеет каждый оператор сравнения, написанный для него.

Живой пример .

Это надоедливое friend int cmp (что раздражает, чем больше у вас в нем участников) может быть обработано еще большим вспомогательным кодом:

namespace utils {
  template<class...Ts>
  int cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs );
  template<class T, class...LowPriority>
  int cmp( T const& lhs, T const& rhs, LowPriority&&... );

  template<class...Ts, std::size_t...Is>
  int tuple_cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs, std::index_sequence<Is...> ) {
    int result = 0;
    ( (result = cmp( std::get<Is>(lhs), std::get<Is>(rhs) )) && ... );
    return result;
  }

  template<class...Ts>
  int cmp( std::tuple<Ts...> const& lhs, std::tuple<Ts...> const& rhs ) {
     return tuple_cmp( lhs, rhs, std::make_index_sequence<sizeof...(Ts)>{} );
  }
  template<class T, class...LowPriority>
  int cmp( T const& lhs, T const& rhs, LowPriority&&... ) {
    if (lhs < rhs) return -1;
    if (rhs < lhs) return 1;
    return 0;
  }
}

, который еще более загадочный код, но вы получаете более простой bob:

struct bob : utils::use_cmp<bob>
{
  int x, y;
  bob( int x_, int y_ ):x(x_), y(y_) {}

  friend auto as_tie(bob const& b) {
    return std::tie(b.x,b.y);
  }
  friend int cmp( bob const& lhs, bob const& rhs ) {
    return utils::cmp( as_tie(lhs), as_tie(rhs) );
  }
};

Обратите внимание, однако, что все это сделано и лучше на operator<=> в .

Живой пример .

Воспользуйтесь чужим решением

Это похоже на подход, который boost :: operator использует для написания этих операторов для вас.

0 голосов
/ 06 сентября 2018

достаточно ли, чтобы операторы были равны ("=")

Оператор равенства в c ++ равен ==

ИЛИ мне нужно перегрузить оператор ("> ="), чтобы иметь функциональность для него?

Это зависит от того, что вы подразумеваете под функциональностью. Если вы имеете в виду, что если вы определите operator== и operator>, компилятор автоматически сгенерирует для вас operator>=? Нет, не нужно, вам нужно реализовать это с использованием существующих операторов или нет.

0 голосов
/ 06 сентября 2018

operator >= не является комбинацией operator > и operator =. operator >= - это собственный оператор, но вы можете реализовать его в терминах operator < Как правило, у вас будет что-то вроде

inline bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator!=(const X& lhs, const X& rhs){return !operator==(lhs,rhs);}
inline bool operator< (const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator> (const X& lhs, const X& rhs){return  operator< (rhs,lhs);}
inline bool operator<=(const X& lhs, const X& rhs){return !operator> (lhs,rhs);}
inline bool operator>=(const X& lhs, const X& rhs){return !operator< (lhs,rhs);}

От sbi's answer on Каковы основные правила и идиомы для перегрузки операторов?

0 голосов
/ 06 сентября 2018

Используя очевидную запись, "> || ==" на самом деле является чрезмерным требованием для >=.

Хотя обратите внимание, что для всех реляционных операторов вам действительно нужно <, поскольку эквивалентность устанавливается, если a < b и b < a оба являются ложными. Фактически это одна из концепций, используемых в упорядоченных контейнерах стандартной библиотеки C ++.

...