在 C++ 中设计点积运算符

designing a dot product operator in c++

本文关键字:运算符 C++      更新时间:2023-10-16

我希望能够编写像a = b.c这样的语句;其中b和c是std::vector,a是它们的标量点积(double)。为此,我应该将点积操作与"."符号相关联。这可能吗?

不能覆盖点运算符 ( . )。

而且,即使你可以,你也不应该为此目的。 重写运算符时,应遵循以下三个规则:

  1. 如果运算符的含义不明确,则不应重载。
  2. 始终符合运算符的已知语义。
  3. 始终为所有相关运算符组提供重载。

你的预期设计违反了第二条规则:你希望彻底改变点运算符的语义。

与其这样做,不如提供自己的函数来执行点操作。

请参阅此链接。我认为定义一个 dot() 函数比重载"."要好得多。点符号具有非常具体的功能,如果可以的话),重载它真的会找麻烦<</p>

div class="answers>

'." 符号不能重载,它有固定的含义。此外,要将点积添加到 std::vector(尽管我不建议使用这种方法),您需要从 std::vector 创建一个新的派生类。相反,我建议创建自己的向量类,或者找到一个现有的向量类。

这是一篇关于设计一个好的 c++ 向量类的一些建议的博客文章。http://www.reedbeta.com/blog/2013/12/28/on-vector-math-libraries/

虽然 C++ . 运算符不能重载,但您可以创建类似读取的内容。

#include <iostream>
#include <vector>
#include <utility>

首先,dot_product描述要执行的操作的函数。 如果我让它过于通用,请原谅我:

template<typename T, typename U, typename A1, typename A2>
decltype(std::declval<T>() * std::declval<U>() + std::declval<T>() * std::declval<U>())
dot_product( std::vector<T, A1> const& lhs, std::vector<U, A2> const& rhs )
{
  typedef decltype(std::declval<T>() * std::declval<U>()) product_type;
  typedef decltype( std::declval<product_type>() + std::declval<product_type>()) return_type;
  return_type sum = 0;
  for( std::size_t i = 0; i < lhs.size() && i < rhs.size(); ++i ) {
    sum += lhs[i] * rhs[i];
  }
  return sum;
}

接下来,一些允许我们使用中缀符号的样板

template<typename LHS>
struct half_dot {
  LHS lhs;
  half_dot( LHS&& lhs_ ):lhs(std::forward<LHS>(lhs_)) {}
  template<typename RHS>
  decltype( dot_product( std::declval<LHS>(), std::declval<RHS>() ) )
  operator*( RHS&& rhs ) const {
    return dot_product( std::forward<LHS>(lhs), std::forward<RHS>(rhs) );
  }
};
struct dot_t {};
template<typename LHS>
half_dot<LHS> operator*( LHS&& lhs, dot_t ) {
  return {std::forward<LHS>(lhs)};
}
static dot_t dot;

最后,它的使用示例:

int main() {
  std::vector<int> foo = {1,2,3};
  std::vector<int> bar = {3,2,1};
  std::cout << (foo *dot* bar) << "n";
}

活生生的例子。

您可以重载dot_product做任何您想做的事情,A *dot* B在完成上述样板文件后,将调用dot_product( A, B )并返回结果。