繁体   English   中英

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

[英]How to correctly and safely implement C++ arithmetic operators for std::array?

我正在寻找以最小的开销为std :: array正确,安全地实现C ++(17)算术运算符的方法。

我首先尝试通过将此类运算符实现为非成员函数并将运算符采用的参数限制为具有相同算术value_types和相同大小的数组来实现上述目标。 下面给出两个例子。

template< typename T1, std::size_t N1, typename T2, std::size_t N2 >
constexpr inline auto operator-( const std::array< T1, N1 >& lhs, const std::array< T2, N2 >& rhs )
{
  static_assert( std::is_same< T1, T2 >::value );
  static_assert( std::is_arithmetic< T1 >::value );
  static_assert( N1 == N2 );

  std::array< T1, N1 > result;

  for ( std::size_t i = 0; i < N1; ++i )
  {
    result[ i ] = lhs[ i ] - rhs[ i ];
  }

  return result;
}

template< typename T1, std::size_t N1, typename T2, std::size_t N2 >
constexpr inline auto& operator-=( std::array< T1, N1 >& lhs, const std::array< T2, N2 >& rhs )
{
  static_assert( std::is_same< T1, T2 >::value );
  static_assert( std::is_arithmetic< T1 >::value );
  static_assert( N1 == N2 );

  for ( std::size_t i = 0; i < N1; ++i )
  {
    lhs[ i ] -= rhs[ i ];
  }

  return lhs;
}

我会建议改善上述尝试的建议。 尤其是,我想知道对参数的限制是否正确,并且如果使用减号运算符,可能会过于严格? 此外,我正在征求意见,是否有任何方法可以提高实施效率? 也就是说,有没有比上面的for循环更好的方法来执行实际的算术运算?

通常,应在类型的名称空间中将非成员运算符添加到类型。 否则,将无法通过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;
  }
};

与您的解决方案相比,这有很多改进。 其中,运算符都不是模板,它会产生令人讨厌的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM