【问题标题】:C++ greater than or equal to operatorC++ 大于等于运算符
【发布时间】:2019-02-11 19:22:53
【问题描述】:

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

【问题讨论】:

    标签: c++ operators overloading


    【解决方案1】:

    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 的 answer What are the basic rules and idioms for operator overloading?

    【讨论】:

      【解决方案2】:

      让运算符相等(“=”)就足够了吗

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

      或者我是否需要重载运算符 (">=") 才能为其提供功能?

      这取决于您所说的功能。如果你的意思是如果你定义operator==operator&gt; 编译器会自动为你生成operator&gt;= 吗?不,它不会,你必须使用现有的运算符来实现它。

      【讨论】:

      • 谢谢!我认为编译器会自动执行此操作。
      【解决方案3】:

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

      如果您认为这很糟糕,那您是对的。已经做了很多方法来减少这种情况。我将讨论其中的 4 个。

      等待

      中,如果你正确写operator&lt;=&gt;3-way“宇宙飞船”运算符),或者=default它,那么所有&lt;&lt;=&gt;=&gt;!=== 将为您编写。

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

      上面的bob 现在有每个&lt; == 等C++ 为其编写的运算符。

      写出来

      之前,如果你想要所有这些,你必须把它们都写下来。这是乏味且容易出错的。

      在它们上使用std::tie 和调用&lt; 之类的东西不太容易出错:

      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。这种模式比重复执行&lt;== 更有效。

      使单个strcmplike 函数产生&lt;== 并且可以进行其他比较操作:

      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 的魔力现在已经为它编写了每个比较运算符。

      Live example.

      烦人的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&lt;=&gt; 中完成并且做得更好。

      Live example.

      使用别人的解决方案

      这类似于boost::operators 用来为您编写这些运算符的方法。

      【讨论】:

        【解决方案4】:

        使用一个明显的符号,“&gt; || ==”实际上是对&gt;= 的过度要求。

        虽然请注意,对于 all 关系运算符,您实际上只需要&lt;,因为如果a &lt; bb &lt; a 都为假,则建立等效性。事实上,这是有序 C++ 标准库容器中使用的概念之一。

        【讨论】:

        • 我觉得应该是 > || ==。感谢您的回复!
        • @VasiMarin:哎呀。让我们共同发布!
        • @user463035818:表示可以从"​​>"派生">="。
        • 哦,当然,也许“虽然”应该是“因为”?我想这就是造成我困惑的原因,否则它完全有道理
        猜你喜欢
        • 1970-01-01
        • 2012-11-28
        • 2022-09-24
        • 2019-07-06
        • 1970-01-01
        • 1970-01-01
        • 2011-09-17
        • 2011-03-13
        • 1970-01-01
        相关资源
        最近更新 更多