What's the best way to implement a operator overload? - c++

Among all things I've learned in C++ (which isn't so much), operator overloading seems the most difficult. In general terms, when is it best to write an operator overload as a friend function? When do I have to explicilty use *this? Is always bad to use a temporary object?

There is nothing magical abourt operator overloading - such overloads are simply functions with strange-looking names. So you write operator overloads in the same way you would write a named function. In fact, it's often a good idea to write a named function first - you can always change it to an operator later.
The only thing that you do have to be aware of is that the compiler makes use of a couple of your operators:
operator=() when storing things in collections
operator<() when sorting/searching things

Neil's answer is correct. In addition, this link provides a lot of good information about when, where, why, and how to use the various types of operator overloading in C++.
In general, I'd try to stick with overloads that are intuitive -- use of the '+' operator should reflect something analogous to addition, etc. If you find yourself doing string comparisons with the '+' operator or something like that, you should probably be using standard functions instead.

The first rule of operators overloading: do not overload operators that make no sense. For instance, the + operator may look like a good choice to append elements to lists, but it is not: not everybody would find this use logical.
Regarding the mathematical operators, friend is unneeded.
The typical way to define them (that respects symmetries and implicit conversions) is the following one:
struct T {
T& operator+=(T const& rhs) {
// the actual addition code
return *this;
}
};
T const operator+(T const& lhs, T const& rhs) {
return T(lhs) += rhs;
};
However, this organization is not adapted to operators like Matrix or
Polynomial multiplication as the *=(T const&) operator is not that trivial. In that
case, we would define operator*=(T const&) on top of operator*(T const&, T const&), and the binary operator*() could be made friend if there is no accessor to the internal data -- this use of friend is not an encapsulation violation, but an encapsulation enforcement --, or for optimization purposes.
If you really want to eliminate most temporaries, have a look at expression templates (see Blitz++, boost.ublas, newmat, ...), or wait for C++0x rvalue references.

All operators overloads as member-function take *this as lvalue,so you need friend in cases you don't want it such overload stream operators as << and >>.In most others cases the use of friends is to break the principle of least privilege.
Other way to overload an operator ,which wasn't said, is to use a global function.

Related

operator& that returns an int and operates on 2 vectors?

I would like to define an & operator between two std::vector<int>. This operator should bit-wise and each element of both vectors together and return the number of non-zero components of the resulting vector.
However, if I define int operator&(const std::vector<int> &lhs, const std::vector<int> &rhs), it the compiler doesn't like it and requires operator& to return a boolean. Is this actually a restriction with operator&?
I would like to define an & operator between two std::vector<int>.
You may not (at least not globally; it can in theory be done in a custom namespace but I recommend against it). Operator overloads for standard templates with no user defined type arguments are reserved to the standard library.
I recommend writing a regular function instead.
Any idea why there's that restriction?
Because this restriction allows the standard library to change and add any operator overload that the committee wishes without breaking previously well defined programs that have their own conflicting overloads (by virtue of not allowing such overloads to be defined).
operator& to return a boolean. Is this actually a restriction with operator&?
No. This is actually not a restriction of binary operator&. It may return int.

How to make operators work from the left of the object?

This feels like too basic a question to not have asked already so if it's already out there I'd accept the link as the answer or delete this post if you fellas see fit, personally I couldn't find it anywhere at least so perhaps this'll be useful to others...
So yeah, like it's said in the title, how do I make operators that'd let me work from the left side of the object? f.e:
++obj
variable * obj
etc
If I wanted to work on the right side of that 'obj' I'd make something like
obj operator*(const variable &t){...} //for obj * variable operation
intuitively I tried
obj *operator(const variable &t){...} //for variable * obj operation(?)
to make it work the other way around but of course, that didn't work, any suggestions?
Ummm you cannot do that. I mean, choose which side the operator works on. It is defined by the standard. The operators in c++ do not have sides they operate on. All are different operators. The operator you overload is defined by the signature.
The "side" has meaning only for the unary operators anyway. For binary operators it is either a member function called on the left operand, with right operand passed as an argument, or a free standing function.
The case that "allows definition of the side" is ++ and --. And it is a special case. ++c and c++ are actually two different operators in terms of language -- pre- and post- incrementation. The differentiation between realized by a "bogus" parameter in the overload: http://en.cppreference.com/w/cpp/language/operator_incdec.
There are other unary operators too, and you cannot choose side E.g: !, ~, there are no suitable overloads defined for "right side" cases.
Other disambiguation is also done via parameters. * used for both, member access and arithmetic operation. The operator which you overload is defined by number of parameters.
T T::operator*(const T2 &b) const; is artithmetic one, and R& T::operator*(); is member access.
Here you can find rules for all operators: http://en.cppreference.com/w/cpp/language/operators.
Aaand since its c++ you can abuse it. Unrecommended though.
You can overload function and make that function friend of the class.
variable operator*(const variable &, const variable *);
class variable {
friend variable operator*(const variable &, const variable *);
};

c++ operator overloading how to implement the pattern like the ctor of Mat_<type> in opencv

In opencv, I can construct an object of Mat like this:
Mat mat = (Mat_<int>(2, 3) << 1, 2, 3, 4, 5, 6);
So it's convenient to initialize an instance of Mat_<type>,and if I have a custom simplified matrix class Mat2D,in which i will use this pattern, but how to do?
Update: I tried to use variable length parameter list, but error C2829: 'operator <<' cannot have a variable parameter list.
WARNING: DO NOT DO THIS. YOU HAVE BEEN WARNED.
You can achieve this using operator overloading, but it is a very bad idea, as I'll explain later.
I'll assume class Mat has a constructor that takes a Mat_<int>.
I'll assume class template Mat_<T> has a method, Insert(), that knows how to insert a single element into a matrix. I'll let you work this out, but it'll need a way to know where to insert it.
Using this method it is easy to overload operator<<:
template<typename T>
Mat_<T>& operator<<(Mat_<T>& mat, const T& el)
{
mat.Insert(el);
return mat;
}
And we can overload operator, to call this overloaded operator<<:
template<typename T>
Mat_<T>& operator,(Mat_<T>& mat, const T& el)
{
return mat << el;
}
Everything works fine and you can use your syntax. Now I will explain why this is a bad idea.
Overloading operator<< this way is perfectly sensible. This is the insertion operator and our overload inserts an element into the matrix. This is what anybody would expect; so far, so good.
But overloading operator, is not. The meaning of this operator is "evaluate two expressions, then return the last one"; this is clearly not what our overloaded operator does. Unwary users will try to use operator , in the standard way (for instance, in a for loop) and will not understand why their code does not work. You should never overload an operator to do a non-standard operation unless you want to be hated by whoever uses your code; probably yourself sometime later.
In fact, while the standard allows overloading operator,, this is something you should probably never do, because it is impossible to write code that does the standard operation. You can consider this a mistake in the standard that is kept for backward compatibility.
And, in case you were considering overloading operator, to take two int and somehow bundle them together, not only the drawbacks are even more serious: it is illegal to overload an operator when all operands are built-in types.
So, in summary: you can do it, but it is a bad idea and will cause bugs in unexpected places of your code.
This is a combination of builder pattern with fluent interface using the inserter and comma operators as simple DSL. I do not see dangers of any kind (if done properly), since your DSL defines a very special context in which these operators apply. Have a look at boost::assign, if you are looking for inspiration. Anyway, I´d use verbal DSL elements instead of operators but this is just a matter of my personal preference...

Overloading += in c++

If I've overloaded operator+ and operator= do I still need to overload
operator+= for something like this to work:
MyClass mc1, mc2;
mc1 += mc2;
Yes, you need to define that as well.
A common trick however, is to define operator+=, and then implement operator+ in terms of it, something like this:
MyClass operator+ (MyClass lhs, const MyClass& rhs){
return lhs += rhs;
}
If you do it the other way around (use + to implement +=), you get an unnecessary copy operation in the += operator which may be a problem i performance-sensitive code.
operator+= is not a composite of + and =, therefore you do need to overload it explicitly, since compiler do not know to build puzzles for you. but still you do able to benefit from already defined/overloaded operators, by using them inside operator+=.
Yes, you do.
If the real question here is, "I don't want to write a load of repetitive operators, please tell me how to avoid it", then the answer may be:
http://www.boost.org/doc/libs/1_38_0/libs/utility/operators.htm
The syntax looks a little fiddly, though. As I've never used it myself, I can't reassure you that it's simple really.

Canonical operator overloading?

Is there a canonical or recommended pattern for implementing arithmetic operator overloading in C++ number-like classes?
From the C++ FAQ, we have an exception-safe assignment operator that avoids most problems:
class NumberImpl;
class Number {
NumberImpl *Impl;
...
};
Number& Number::operator=(const Number &rhs)
{
NumberImpl* tmp = new NumberImpl(*rhs.Impl);
delete Impl;
Impl = tmp;
return *this;
}
But for other operators (+, +=, etc..) very little advice is given other than to make them behave like the operators on built-in types.
Is there a standard way of defining these? This is what I've come up with - are there pitfalls I'm not seeing?
// Member operator
Number& Number::operator+= (const Number &rhs)
{
Impl->Value += rhs.Impl->Value; // Obviously this is more complicated
return *this;
}
// Non-member non-friend addition operator
Number operator+(Number lhs, const Number &rhs)
{
return lhs += rhs;
}
In Bjarne Stroustrup's book "The C++ Programming Language", in chapter 11 (the one devoted to Operator Overloading) he goes through witting a class for a complex number type (section 11.3).
One thing I do notice from that section is that he implements mixed type operations... this is probably expected for any numeric class.
In general, what you've got looks good.
The big thing to consider when writing any operator is that member operators do not undergo conversions on the left parameter:
struct example {
example(int);
example operator + (example);
};
void foo() {
example e(3), f(6);
e + 4; // okay: right operand is implicitly converted to example
e + f; // okay: no conversions needed.
6 + e; // BAD: no matching call.
}
This is because conversion never applies to this for member functions, and this extends to operators. If the operator was instead example operator + (example, example) in the global namespace, it would compile (or if pass-by-const-ref was used).
As a result, symmetric operators like + and - are generally implemented as non-members, whereas the compound assignment operators like += and -= are implemented as members (they also change data, meaning they should be members). And, since you want to avoid code duplication, the symmetric operators can be implemented in terms of the compound assignment ones (as in your code example, although convention recommends making the temporary inside the function).
The convention is to write operator+(const T&) and operator-(const T&) in terms of operator+=(const T&) and operator-=(const T&). If it makes sense to add and subtract to/from primitive types then you should write a constructor that constructs the object from the primitive type. Then the overloaded operators will also work for primitive types, because the compiler will call the appropriate constructor implicitly.
As you mentioned yourself, you should avoid giving access privileges to functions that don't need it. But in your code above for operator+(Number, const Number&) I'd personally make both parameters const references and use a temp. I think it isn't surprising the commenter below your question missed this; unless you have a good reason not to, avoid surprises and tricks and be as obvious as possible.
If you want your code to integrate with other numeric types, say std::complex, watch out for cyclic conversions. That is, don't supply operator OtherNumeric() in Numeric if OtherNumeric supplies a constructor that takes a Numeric parameter.
It is traditional to write the operator X in terms of the operator =X
It is also traditional the all parameters to the standard operators are const
// Member operator
// This was OK
Number& Number::operator+= (Number const& rhs)
{
Impl->Value += rhs.Impl->Value; // Obviously this is more complicated
return *this;
}
// Non-member non-friend addition operator
Number operator+(Number const& lhs,Number const& rhs)
{
// This I would set the lhs side to const.
// Make a copy into result.
// Then use += add the rhs
Number result(lhs);
return result += rhs;
}
You mention assignment operator.
But you did not mention the copy constructor. Since your class has ownership of a RAW pointer I would expect you to define this as well. The Assignment operator is then traditionally written in terms of the copy constructor.