0

I would like to be able to write statements like a = b.c; where b and c are std::vector and a is their scalar dot product (double). For doing this, I should associate the dot product operation with '.' symbol. Is this possible?

Hari
  • 1,561
  • 4
  • 17
  • 26
  • 2
    http://stackoverflow.com/questions/520035/why-cant-you-overload-the-operator-in-c – AAA Dec 31 '13 at 17:44
  • 4
    The better solution is to actually define a `DotProduct` function as it will be more clear than overloading `operator.` and will keep any future programmers who have to look at/maintain your code from hunting you down while you sleep ... – Zac Howland Dec 31 '13 at 17:46
  • 1
    Note as well that the STL already has `std::inner_product` in `` that will work with `std::vector`s – A.E. Drew Dec 31 '13 at 17:51
  • If you're concerned about syntax, you could use [Yakk's named operator approach](http://codereview.stackexchange.com/questions/23179/named-operators-in-c). It allows infix notation like `a = b *dot* c`. – dyp Dec 31 '13 at 17:56
  • It should also be noted that `std::vector` and mathematical vectors are VERY different and you really should use a dedicated class for them. – ECrownofFire Dec 31 '13 at 19:34

4 Answers4

8

You cannot override the dot-operator (.).

Moreover, even if you could you never should for this purpose. When overriding operators, you should follow these three rules :

  1. If the meaning of an operator is ambigious, it should not be overloaded.
  2. Always conform to the operator's well-known semantics.
  3. Always provide overloads for all of a related group of operators.

Your intended design violates the second rule: you wish to drastically change the semantics of the dot-operator.

Instead of doing this, you should provide your own function to perform the dot operation.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
2

See this link. I think it would be much much better to define a dot() function than to overload ".". The dot symbol has very specific functionality and you would really be looking for trouble by overloading it (if you even could)

Community
  • 1
  • 1
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
0

The '.' symbol cannot be overloaded, it had a fixed meaning. Additionally, to add a dot product to std::vector (although I don't advise this approach) you would need to create a new derived class from std::vector. Instead, I suggest making your own vector class, or find an existing one.

Here is a blog post on some advise on designing a good c++ vector class. http://www.reedbeta.com/blog/2013/12/28/on-vector-math-libraries/

Lokno
  • 590
  • 3
  • 15
0

While the C++ . operator cannot be overloaded, you can make something that reads similarly.

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

First, the function dot_product that describes the operation you want to do. Forgive me if I make it overly generic:

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;
}

Next, some boilerplate that allows us to use infix notation:

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;

Finally, an example of its use:

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

live example.

You can overload dot_product to do whatever you want, and A *dot* B will invoke dot_product( A, B ) and return the result, after doing the above boilerplate.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524