如何正确安全地为std :: array实现C ++算术运算符?

时间:2018-03-19 19:16:12

标签: c++ operator-overloading c++17

我正在为std :: array寻找一个正确而安全的C ++(17)算术运算符实现,并且开销最小。

在第一次尝试中,我尝试通过实现非成员函数等运算符并将运算符所采用的参数限制为具有相同算术value_types且大小相同的数组来实现上述目的。下面给出两个例子。

post=?id=30

我希望有关改善上述尝试的建议。特别是,我想知道对参数的限制是否正确,并且在减号运算符的情况下甚至可能过于严格?此外,如果有任何方法可以提高实施效率,我会征求意见吗?也就是说,有没有比上面给出的for循环更好的方法来进行实际的算术运算?

1 个答案:

答案 0 :(得分:1)

作为一般规则,应在类型的命名空间中添加非成员运算符。如果不这样做,您的操作员将无法通过ADL找到,这会导致持续的痛苦。

将非成员运营商添加到namespace std

是不合法的

所以,妙语是,不要这样做。

相反,试试这个:

template<class T, std::size_t N>
struct vecarray : std::array<T,N> {
  static_assert( std::is_arithmetic< T >::value );
  using std::array<T,N>::array;
  vecarray& operator+=( std::array<T,N> const& rhs )& {
    for (auto& x:*this) {
      x += rhs[ std::addressof(x)- this->data() ];
    }
    return *this;
  }
  vecarray& operator-=( std::array<T,N> const& rhs )& {
    for (auto& x:*this) {
      x -= rhs[ std::addressof(x)- this->data() ];
    }
    return *this;
  }
  vecarray& operator*=( std::array<T,N> const& rhs )& {
    for (auto& x:*this) {
      x *= rhs[ std::addressof(x)- this->data() ];
    }
    return *this;
  }
  vecarray& operator/=( std::array<T,N> const& rhs )& {
    for (auto& x:*this) {
      x /= rhs[ std::addressof(x)- this->data() ];
    }
    return *this;
  }

  friend vecarray operator+( vecarray lhs, std::array<T, N> const& rhs ) {
    lhs += rhs;
    return lhs;
  }
  friend vecarray operator-( vecarray lhs, std::array<T, N> const& rhs ) {
    lhs -= rhs;
    return lhs;
  }
  friend vecarray operator*( vecarray lhs, std::array<T, N> const& rhs ) {
    lhs *= rhs;
    return lhs;
  }
  friend vecarray operator/( vecarray lhs, std::array<T, N> const& rhs ) {
    lhs /= rhs;
    return lhs;
  }
};

这对您的解决方案有很多改进。其中,没有一个操作符是模板,这会产生非常恼人的错误。