0

I'm overloading a vector operator '-' and trying difference reference method. The code that test the operator is

pos-(norm-bias)

where pos, norm and bias are all instances of the class Vector.

Constant reference worked:

Vector operator-(const Vector& v) {

However, I don't understand why without the 'const' keyword would result in an error: Invalid operands to binary expressions.

Vector operator-(Vector& v) {

Furthermore, I don't understand why "const Vector&& v" with rvalue reference failed.

Vector operator-(const Vector&& v) {
Strin
  • 677
  • 9
  • 15

2 Answers2

4

You haven't provided much information, so I'm going to assume all 3, pos, norm and bias, are instances of Vector.

Let's consider the expression pos-(norm-bias). First the subtraction within the parentheses is performed. Your operator- returns a new Vector object by value. So the result of the first subtraction will now try to bind to pos.operator-(). But rvalues cannot bind to non-const references and the code will not compile unless your operator- takes its argument by const reference.

Now if you change the signature to Vector operator-(const Vector&& v), the very first subtraction, (norm - bias) will fail because bias is an lvalue and it will not be able to bind the rvalue reference parameter.

What you might want to do is provide two overloads, one that takes a const reference, and another that takes an rvalue reference.

Vector operator-(const Vector& v);
Vector operator-(Vector&& v);

In the second operator, you could potentially steal resources from the argument and avoid expensive operations such as memory allocation. Whether you could actually benefit from such an overload is impossible to tell without knowing what your Vector class contains and does.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
0

The correct overloads you want are:

Vector operator-(const Vector& v) const;
Vector operator-(Vector&& v) const;

Note that you want to mark the method themselfs as const as well, because otherwise you will run into more problems when you have expressions like (pos-norm)-bias (whether that example makes sense or not). In the long run, if you really want to exploit move semantics, you actually want to do more, as the left-hand side might also be movable and you want to complete the set of operators with -=. In the end, you probably want two member functions:

Vector& operator-=(const Vector& v);
Vector& operator-=(Vector&& v);

and a set of four free functions:

Vector operator-(const Vector& lhs, const Vector& rhs);
Vector operator-(const Vector& lhs, Vector&& rhs);
Vector operator-(Vector&& lhs, const Vector& rhs);
Vector operator-(Vector&& lhs, Vector&& rhs);

The latter can be improved/optimized further by having it automatically generated for you, consider using a library like Boost.Operators or my df.operators to help you with that.

Generally, you might want to read the FAQ for operator overloading.

Community
  • 1
  • 1
Daniel Frey
  • 55,810
  • 13
  • 122
  • 180