C++大于或等于运算符

Vas*_*rin 14 c++ overloading operators

在C++中,对于大于或等于("> =")的运算符,是否足以让运算符等于("=")和更大(">")重载以具有大于或等于的功能( "> =")?或者我是否需要重载运算符("> =")以使其具有功能?

Nat*_*ica 14

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);}
Run Code Online (Sandbox Code Playgroud)

来自sbi的回答有关运算符重载的基本规则和习惯用法是什么?


Sla*_*ica 13

是否足以使运算符相等("=")

c ++中的等于运算符是 ==

或者我需要重载运算符("> =")以使其具有功能吗?

这取决于你的功能.如果你的意思是,如果你定义operator==并且operator>编译器会operator>=为你自动生成?不,它不会,你必须使用现有的运营商来实现它.


Yak*_*ont 11

不,C++不会为您编写这些运算符.

如果你认为这很糟糕,那你就是对的.已经完成了许多减少这种麻烦的方法.我会谈谈他们中的4个.

等等

,如果你写operator<=>(在3路 "宇宙飞船"运营商)正确,或者=default,那么这一切<,<=,>=,>,!===会为你写的.

struct bob {
  int x,y;
  auto operator<=>( bob const& )const = default;
};
Run Code Online (Sandbox Code Playgroud)

上面bob< ==C++为它编写的每个etc运算符.

写下来吧

之前,如果你想要所有这些,你必须编写所有这些.这很乏味且容易出错.

在它们上使用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);
  }
};
Run Code Online (Sandbox Code Playgroud)

甚至

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);
  }
};
Run Code Online (Sandbox Code Playgroud)

因为tuple做了适当的词汇比较; 写没有错误的词汇比较令人讨厌.

以它为中心的方式进行Metaprogram

比较你经常使用的字符串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); }
  };
}
Run Code Online (Sandbox Code Playgroud)

现在我们有一个类型:

struct bob {
  int x, y;
};
Run Code Online (Sandbox Code Playgroud)

我们希望能够在其上使用比较运算符:

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;
  }
};
Run Code Online (Sandbox Code Playgroud)

并且使用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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是更神秘的代码,但你得到一个更简单的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) );
  }
};
Run Code Online (Sandbox Code Playgroud)

但请注意,所有这些都是operator<=>完成的并且更好.

实例.

使用别人的解决方案

这与boost ::运算符用于为您编写这些运算符的方法类似.


Bat*_*eba 9

使用一个明显的表示法," >|| =="实际上是一个过度要求>=.

虽然请注意,对于所有关系运算符,您实际上只需要<,因为等价是建立的,如果a < b并且b < a都是假的.实际上,这是有序C++标准库容器中使用的概念之一.