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.
Related
I am having trouble trying to understand why someone would want to overload an operator. I understand it can help reassign functionality, but it takes away key functionalities as well.
In an assignment given to me, I was given a skeleton code that Vector4f overloaded =, and now in Matrix4f.h, I can't use = when creating a function to turn a matrix into an identity matrix (the matrix is set to a float, not int).
Is the original functionality lost, or do I need to type cast the = somehow? Also, why is even reassigning core functionality operators a good idea? My professor had suggested that we could have done add() and overloaded that, but didn't.
Operator overloading is a way of adding some syntactic sugar to help your types have a full, semantically-coherent API.
Take, for example, std::string. In terms of pure assignment operators, it provides a number of ways to help the string behave in a coherent and semantically-sound way. In addition to the copy/move operator= overloads, it supplies:
operator=(CharT): Assign to a character
operator=(const CharT*): Assign to a string-literal or pointer to C-style string
Which allow it to behave in a way that the consumer would expect, such as:
auto str = std::string{""};
str = "hello world"; // c-style string/string literal
str = 'c';
Other operators in this example would be:
operator+(const CharT*): append c-strings/string literals
operator+(CharT): append characters
operator+(const basic_string&): append other std::strings
Equality or comparison operators (operator==, operator<, etc): comparing things in a coherent way
Adding operators doesn't remove functionality. It helps to extend the functionality by providing a semantically clear way of writing code.
Note: The assignment operator is a special case, in that some circumstances may result in the compiler-generated operator= to be deleted. However, you can always define it by-hand, or explicitly use the = default syntax to re-enable it. For example:
class Foo
{
public:
...
Foo& operator=(const Foo&) = default; // Explicitly ask for the compiler-generated one
};
Languages that do not support operators like this may result in having to write code with everything written out. For example:
string("hello").append(' ').append("world")
instead of simply
std::string{"hello"} + ' ' + "world";
(these are contrived examples)
Edit: The answer above focuses more on your immediate question as to why to overload operators. Your error, as seen in your screenshot, appears to be due to a lacking operator= overload for assigning an int (or some other numerically convertible type, like a float) to the Vector4f type. Defining a custom operator would enable this.
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 *);
};
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...
Even after years C++ is confusing the hell out of me..
My class implements
virtual CStatCounter& operator= (CStatCounter const& inSC);
and
virtual CStatCounter operator+(const CStatCounter& rhs);
And I'm keeping a
vector<CStatCounter*> mStatistics
somewhere else. Now all I'm trying to do is accumulate all values.
After being laughed at by std::accumulate I've switched to a simple loop rolled on my own, still no luck:
CStatCounter *iniCounter = new CStatCounter(0);
BOOST_FOREACH (CStatCounter *counter, mStatistics)
{
iniCounter = iniCounter+counter;
}
The compiler (Xcode 4.2/clang) complains about
Invalid operands to binary expression ('CStatCounter *' and 'CStatCounter *')
I can change the loop body to counter+counter and it still fails with the same error message.
Shouldn't it be smart enough to implicitly convert between references and pointers?
Am I missing something trivial here?
Shouldn't it be smart enough to implicitly convert between references
and pointers?
It could, but that wouldn't be C++, would it? When you can overload operators for every conceivable combination of operands, it's really not safe to make such assumptions.
Am I missing something trivial here?
Dereferencing:
*iniCounter = *iniCounter + *counter;
By the way, you can still use std::accumulate, you just need a custom binary operation, like this:
CStatCounter MyAddFunc(const CStatCounter & lhs, const CStatCounter * rhsp)
{
return lhs + *rhsp;
}
*iniCounter = std::accumulate(mStatistics.begin(), mStatistics.end(),
*iniCounter, MyAddFunc);
How about *iniCounter = *iniCounter + *counter;?
On a side note, are you sure all those pointers and virtuals are really necessary?
There is no implicit conversion here.
You will have to either provide exact overloads which you make use of.
virtual bool operator+(const CStatCounter* rhs);
virtual CStatCounter& operator= (CStatCounter const* inSC);
or modify your code to match the overloads you provided.
*iniCounter = *iniCounter + *counter;
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.