整理C ++运算符重载

时间:2014-11-27 10:33:39

标签: 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

它仍然感觉不太正确。

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

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

1 个答案:

答案 0 :(得分:8)

为什么不使用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上运行示例。