c++11 - 整理 C++ 运算符重载

标签 c++11 design-patterns operator-overloading

我一直在整理一些旧的 C++ 代码。

我使用几个宏减少了运算符重载函数的页面:

.hpp

    // for context, Long and Object wrap respective Python primitives
    class Long: public Object
    {...};    

#define OPS( A, B ) \
    bool operator == ( A, B ); \
    bool operator != ( A, B ); \
    bool operator >  ( A, B ); \
    bool operator <  ( A, B ); \
    bool operator >= ( A, B ); \
    bool operator <= ( A, B );

#define UNI( A ) \
    OPS( A, A )

#define BI_( A, B ) \
    OPS( A, B ) \
    OPS( B, A )

    UNI( const Long&  )
    BI_( const Long& , int )
    BI_( const Long& , long )

    UNI( const Float&  )
    BI_( const Float& ,  double )

#undef BI_
#undef UNI
#undef OPS
#undef OP

.cpp

#define OP( op, l, r, cmpL, cmpR ) \
    bool operator op( l, r ) { return cmpL op cmpR; }

#define OPS( ... ) \
    OP( != , ##__VA_ARGS__ ) \
    OP( == , ##__VA_ARGS__ ) \
    OP( >  , ##__VA_ARGS__ ) \
    OP( >= , ##__VA_ARGS__ ) \
    OP( <  , ##__VA_ARGS__ ) \
    OP( <= , ##__VA_ARGS__ )

#define BI_( a, b, convA, convB ) \
    OPS( a, b, convA, convB ) \
    OPS( b, a, convB, convA )

    OPS( const Long&  a, const Long&  b  ,  a.as_long()      , b.as_long()    )
    BI_( const Long&  a, int          b  ,  a.as_long()      , b              )
    BI_( const Long&  a, long         b  ,  a.as_long()      , b              )

    OPS( const Float& a, const Float& b  ,  a.as_double()    , b.as_double()  )
    BI_( const Float& a, double       b  ,  a.as_double()    , b              )

#undef BI_
#undef OPS
#undef OP

感觉还是不太对。

它将类分布在三个不同的位置:类声明本身、稍后在同一 header 中的运算符声明,然后在单独的 .cxx 文件中实际定义。

在 C++11 中是否有更简洁的方法来实现这些运算符?

最佳答案

为什么不使用 CRTP提供所有运算符的基类?

template<typename C, typename T>
struct ops_base
{
  friend bool operator==(const ops_base& l, const ops_base& r)
  {
    const C& cl = static_cast<const C&>(l);
    const C& cr = static_cast<const C&>(r);
    return (caster<C, T>::cast(cl) == caster<C, T>::cast(cr));
  }

  friend bool operator==(const ops_base& l, T r)
  {
    const C& cl = static_cast<const C&>(l);
    return (caster<C, T>::cast(cl) == r);
  }

  friend bool operator==(T l, const ops_base& r)
  {
    const C& cr = static_cast<const C&>(r);
    return (l == caster<C, T>::cast(cr));
  }

  friend bool operator!=(const ops_base& l, const ops_base& r)
  { return !(l == r); }

  friend bool operator!=(const ops_base& l, T r)
  { return !(l == r); }

  friend bool operator!=(T l, const ops_base& r)
  { return !(l == r); }

  friend bool operator<(const ops_base& l, const ops_base& r)
  {
    const C& cl = static_cast<const C&>(l);
    const C& cr = static_cast<const C&>(r);
    return (caster<C, T>::cast(cl) < caster<C, T>::cast(cr));
  }

  friend bool operator<(const ops_base& l, T r)
  {
    const C& cl = static_cast<const C&>(l);
    return (caster<C, T>::cast(cl) < r);
  }

  friend bool operator<(T l, const ops_base& r)
  {
    const C& cr = static_cast<const C&>(r);
    return (l < caster<C, T>::cast(cr));
  }

  friend bool operator>(const ops_base& l, const ops_base& r)
  {
    const C& cl = static_cast<const C&>(l);
    const C& cr = static_cast<const C&>(r);
    return (caster<C, T>::cast(cl) > caster<C, T>::cast(cr));
  }

  friend bool operator>(const ops_base& l, T r)
  {
    const C& cl = static_cast<const C&>(l);
    return (caster<C, T>::cast(cl) > r);
  }

  friend bool operator>(T l, const ops_base& r)
  {
    const C& cr = static_cast<const C&>(r);
    return (l > caster<C, T>::cast(cr));
  }

  friend bool operator<=(const ops_base& l, const ops_base& r)
  { return !(l > r); }

  friend bool operator<=(const ops_base& l, T r)
  { return !(l > r); }

  friend bool operator<=(T l, const ops_base& r)
  { return !(l > r); }

  friend bool operator>=(const ops_base& l, const ops_base& r)
  { return !(l < r); }

  friend bool operator>=(const ops_base& l, T r)
  { return !(l < r); }

  friend bool operator>=(T l, const ops_base& r)
  { return !(l < r); }
};

然后像这样使用它:

struct Long : ops_base<Long, long>
{
  Long(long val) : value_(val) { }

  long as_long() const { return value_; }

private:
  long value_;
};

struct Float : ops_base<Float, double>
{
  Float(double val) : value_(val) { }

  double as_double() const { return value_; }

private:
  double value_;
};

ideone 上运行示例.

关于c++11 - 整理 C++ 运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27168446/

相关文章:

C++ 重载运算符 +

c++ - std::lock()定义不正确,无法实现还是没用?

c++ - 是否可以在对象实例化期间定义 std::array 类成员的元素计数?

C++ 为什么不能在 constexpr 函数中调用字符串大小函数

c++ - 关于函数引用和线程的问题

ruby-on-rails - 如何在 Rails 中将非持久数据添加到模型中?

java - Java 中的泛型方法模式

C++ - 为默认类型重载赋值运算符

每个字符串的javascript单例对象

c++ - 为什么我不能创建一个结构对象类型的优先级队列?