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?
-
2http://stackoverflow.com/questions/520035/why-cant-you-overload-the-operator-in-c – AAA Dec 31 '13 at 17:44
-
4The 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
-
1Note 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 Answers
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 :
- If the meaning of an operator is ambigious, it should not be overloaded.
- Always conform to the operator's well-known semantics.
- 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.
- 99,718
- 31
- 186
- 324
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)
- 1
- 1
- 114,268
- 16
- 167
- 218
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/
- 590
- 3
- 15
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";
}
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.
- 262,606
- 27
- 330
- 524