Why not overload operator+=() for std::vector? - c++

I've started learning C++, so I don't know in my lack of knowledge/experience why something so seemingly simple to a rookie as what I'm about to describe isn't already in the STL. To add a vector to another vector you have to type this:
v1.insert(v1.end(), v2.begin(), v2.end());
I'm wondering whether in the real world people just overload the += operator to make this less verbose, for example to the effect of
template <typename T>
void operator+=(std::vector<T> &v1, const std::vector<T> &v2) {
v1.insert(v1.end(), v2.begin(), v2.end());
}
so then you can
v1 += v2;
I also have this set up for push_back to "+=" a single element to the end. Is there some reason these things should not be done or are specifically avoided by people who are proficient in C++?

This is actually a case where I would like to see this functionality in the form of an overload of append(). operator+= is kinda ambiguous, do you mean to add the elements of each vector to each other? Or you mean to append?
However, like I said, I would have welcomed: v1.append(v2); It is clear and simple, I don't know why it isn't there.

I think the main reason is that the semantics of += aren't obvious. There's the meaning that you have here, but there's also an equally valid meaning, which is element-wise addition of each element of equal-sized vectors. Due to this ambiguity I assume they decided it was better to rely on the user to call insert diretly.

Operators should be overloaded only when you are not changing the meaning of those operators.*
What that means is, for example, if there is no mathematical definition of the product of two objects, don't overload the multiplication operator for those objects. If there was a mathematical correspondence, operators overloading can make a class more convenient to use by allowing equations to be expressed in the form a*b + c rather than the more verbose (a.multiply(b)).add(c) Where addition and multiplication operators are used, addition and multiplication should be the intent. Any other meaning is more than likely to confuse others. Some other types where overloading operators is acceptable (and, in my opinion, preferable) are smart pointers, iterators, complex numbers, vectors, and bignums.
This follows from one of the design goals of C++, that it should be possible to define classes that are as easy to use as built in types. Of course there are operators you can define on classes which are not mathematical concepts either. You may wish to overload the == and != operators instead of writing an isEqual method, and might want to overload = because the compiler's default assignment operator is not what you want.
On the other hand, overloading an operator to do something unexpected, like defining ^ to translate a string to Japanese, is obscure and dangerous. Your fellow programmers will not be happy to find out that what looked like an exclusive or comparison was actually something very different. The solution then is to write your classes to make it easy to write clear and maintainable code, whether that means using operator overloading or avoiding it.
Adding two vectors is too ambiguous to warrent defining an operator. As others have shown, many people have different ideas of what this means, whereas for a string it is universally understood that adding two strings together means concatenation. In your example, it isn't entirely clear whether you want to do a component wise add on all the elements, add an element to the end, or concat two vectors together. Although it may be more concise to do it that way, using operator overloading to create your own programming language isn't the best way to go.
*Yes, I know Stroustrup overloaded << and >> to do stream operations rather than bitshifts. But those weren't used often compared to arithmetic and pointer operators in the first place, and it could be argued that now that everyone knows how to use cout, it's generally understood that << and >> are the inserter and extractor operators. (He originally tried to use just < and > for input and output, but the meaning of those operators was so ingrained in everyone's minds that the code was unreadable.)

In addition to what others mentioned about this syntax not being intuitive and therefore error prone, it also goes against a good design rule making general algorithms applied to various containers free functions, and container specific algorithms -- member functions. Most containers follow this rule, except std::string, which got a lot of flack from Herb Sutter for its monolithic design.

Related

What is the difference between these different ways to invoke an operator on `this`?

In C++, we can define and overload operators to make the code beautiful. However, when an operator needs to be called from within the class which defines it, the syntax isn't as elegant.
For example, consider the typical use of operator[] on a string:
std::string word("Hello!");
char first = word[0];
Simple. But what if such an operator needs to invoked from within some class which itself defines it? The syntaxes aren't as pretty:
(*this)[i];//option 1
operator[](i);//option 2
this->operator[](i);//option 3
In terms of performance and/or behavior, what is the difference between the three, especially when dealing with inheritance or polymorphism? Which is the proper, unambiguous syntax?
What is the difference between the three, in terms of readability and performance?
There should be no difference in performance no matter which form you use.
As for readability, it's a matter of opinion. I would prefer to use
(*this)[i];
but I wouldn't complain if someone used one of the other forms.
Which is the "correct" way of invoking the operator?
All are correct - syntactically as well as semantically.

Overloading operator without having a class

Can we use operator overloading on non-objects? e.g adding two vector<int>. Or do I need to make a class having vector<int> and then overload the + operator.
Also, I want to know if it is possible to have 2 different types of operands in a binary operator. If yes, how?
Can we use operator overloading on non-objects?
Operators are essentially implemented as functions and can accept a similar range of types as functions do.
There are a few restrictions, in particular, it is limited by the fact that at least one argument must be a class or enum (user or library type).
In addition, there are some operators that have to be implemented as member functions, so they will be associated with a class, but many can be declared and defined outside of a class.
The exact number of arguments is determined by the operator being implemented. Unary operators accept 1 argument, binary operators accept 2 arguments.
Generally, the advice is to offer behaviour similar to the canonical forms, but the language itself does not limit your implementation to just that behaviour.
Also, I want to know if it is possible to have 2 different types of operands in a binary operator. If yes, how?
Yes. Again, just as functions do.
Can we use operator overloading on non-objects? e.g adding two vector.
I think you meant to ask whether it's possible to use operator overloading outside of a class definition. And yes, it definitely is possible as already stated by other people here. Here's a simple example of overloading the '+' operator for a custom 'MyClass' type:
MyClass operator+(const MyClass& a, const MyClass& b)
{
return MyClass(a.value + b.value);
}
However, there is a reason why std::vector doesn't have overloads for arithmetic operators as the result is ambiguous. Do you want '+' to link two vectors together or should the components be added? How do you handle vectors which differ in size? Often, containers of the STL provide special methods for these purposes and don't rely on operators when it's not clear so make sure you've checked the specification of std::vectors
You're free to implement such operators as you see fit, especially with your own types but you risk creating unintuitive behaviour and ultimately, bad code. In the case of std::vector, it might be better to write a function with a descriptive name which operates on std::vector in the way you desire:
std::vector<int> addComponents(const std::vector<int>& a, const std::vector<int>& b);
Can we use operator overloading on non-objects? e.g adding two vector[?]
The premise of your question is broken, because a vector<int> is an object.
Overload all you like.
Also, i want to know if it is possible to have 2 different types of operands in a binary operator.
Try it.
If yes, how?
By typing it.

Overloading logical operators considered bad practice?

Is it a bad idea to overload &&, || or comma operator and Why?
I wouldn't overload operator&& or operator||. Even if you define a class that gives rise to a Boolean algebra (finite sets, for example), it would probably be a better choice to overload operator& and operator|.
The reason is that C++ programmers expect special semantics for operator&& and operator||: they are short-circuited, i.e. don't evaluate their right-hand argument if not necessary. You can't get this behavior by overloading, since you'll be defining a function.
Overloading operator, has been done in e.g. the Boost.Assign library. This is also the only example of its overloading that I know, and I've never even considered overloading it myself. You'd better have a very specific use case for it where no other operator is suited.
For overloading the logical operators in C++, the operands must be evaluated, which isn't the way things normally work with short circuiting of built-in types.
Look at the below link.
Don't overload logical operators in C++
You shouldn't overload any operators in a way that is surprising. :-)
If you can do it in a way that makes sense (not only to you), it is fine to do so.
Like others have said, the logical operators are special in that they have the effect of lazy evaluation. So your overloads should probably preserve this lazy effect, like with expression templates, or only be used where people don't expect this effect anyway.
It is usually a bad idea: those three operators have a sequencing effect which is lost when you overload them. Loosing that sequencing effect can cause arm (i.e. strange bugs) to those not expecting that lost.
There are cases with template expressions where you can keep the sequencing effect, in those cases I see no problem in overloading them.
The overloads of operator, I know of have another problem: they work in such a way that the apparent chains of operation isn't the real one. Usually, they are used in context when it makes no difference, but once in a blue moon, that is another source of a strange bugs.
I'd say it depends on what your overloads are doing. For example, && and || are expected to work as logical conditions, so if your overload semantics work somehow differently, they can confuse other people (or even yourself, if you don't use them for a while and forget what they do). Consider what you would expect the operators to do if you wouldn't know how they are overloaded and if it would be clearer to just use normal methods instead.
As the others have said, missing lazy evaluation is the main reason to avoid overloading logical operators.
However, there is one very good reason to overload them: Expression templates. The Boost.Lambda library does this, and it's very useful!
Its bad idea except situations when your classes represents some logic entity, because overloaded operators will disorientate and can cause new bugs in code.

operator overloading c++

When overloading operators, is it necessary to overload >= <= and !=?
It seems like it would be smart for c++ to call !operator= for !=, !> for operator<= and !< for operator>=.
Is that the case, or is it necessary to overload every function?
Boost operators might be what you are looking for. These will derive most of your operators based on a few fundamental ones.
That C++ does not provide this automatically makes sense, as one could give totally different meanings to < and >, for example (although it would often be a bad idea).
I am going to take a minority viewpoint here. If you already use boost then using boost operators is not that big of a deal. It may be the correct and tested way to do things but adding boost dependency just for the operators is an overkill.
It is possible to write complex C++ programs without boost (which I personally find aesthetically unpleasant) and so to Keep It Simple (Stupid), to answer OP's question, if you overload operator ==, you should also overload operator !=. Same is true for <, >, ++ etc.
Yes, it is necessary, if you want all of them to work the way you want them to work.
C++ does not force any specific semantics on most of the overloadable operators. The only thing that is fixed is the general syntax for the operator (including being unary or binary and things like precedence and associativity). This immediately means that the actual functionality that you implement in your overload can be absolutely arbitrary. In general case there might not be any meaningful connection between what operator == does and what operator != does. Operator == might write data to a file, while operator != might sort an array.
While overloading operators in such an arbitrary fashion is certainly not a good programming practice, the C++ language cannot assume anything. So, no, it cannot and will not automatically use ! == combination in place of !=, or ! > combination in place of <=.
No, you only need to overload operator == and operator <, the standard library will take care of the rest :)
(EDIT: see using namespace std::rel_ops ;)
Yes it is necessary to overload whichever operators you want to be used as you define them - C++ will not make the decision you describe above; however, keep in mind that if the reason you are overloading is to sort your class, than you only need to override the operators used by the sort routine. In the case of the RTL sort algorithm you only need to override < and =.
Yes! They are each technically different operators. C++ compilers are not inherently inference engines, they are parsers/compilers. They will only do as much as you say to do.
http://www.parashift.com/c++-faq-lite/operator-overloading.html, http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
There are a few shortcuts you can use, such as CRTP to get them automatically injected (see the various Compare classes) into your class.
C++ does not, as a language, define any operator in terms of any other overloaded operator. Just because you have operator+, doesn't mean you get operator+= for free (unlike Ruby and Scala). Just because you have operator < and == doesn't mean you get <= for free. Just because you have operator == doesn't mean you get != for free (unlike Ruby and Scala). Just because you have unary operator * (unary) doesn't mean you get operator -> for free.
std::relops (if imported correctly) and provide default definitions, and Boost provides some mix-ins that define all of the comparison operators in terms of < and ==.
You can use overloading to use user defined names.
Operator overloading means using the same operator to do perform operation on different items which are not in that category. Function overloading means using the same name of function but different arguments, so as to overcome the overhead when the same function is called during looping.

What makes Scala's operator overloading "good", but C++'s "bad"? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Operator overloading in C++ is considered by many to be A Bad Thing(tm), and a mistake not to be repeated in newer languages. Certainly, it was one feature specifically dropped when designing Java.
Now that I've started reading up on Scala, I find that it has what looks very much like operator overloading (although technically it doesn't have operator overloading because it doesn't have operators, only functions). However, it wouldn't seem to be qualitatively different to the operator overloading in C++, where as I recall operators are defined as special functions.
So my question is what makes the idea of defining "+" in Scala a better idea than it was in C++?
C++ inherits true blue operators from C. By that I mean that the "+" in 6 + 4 is very special. You can't, for instance, get a pointer to that + function.
Scala on the other hand doesn't have operators in that way. It just has great flexibility in defining method names plus a bit of built in precedence for non-word symbols. So technically Scala doesn't have operator overloading.
Whatever you want to call it, operator overloading isn't inherently bad, even in C++. The problem is when bad programmers abuse it. But frankly, I'm of the opinion that taking away programmers ability to abuse operator overloading doesn't put a drop in the bucket of fixing all the things that programmers can abuse. The real answer is mentoring. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
None-the-less, there are differences between C++'s operator overloading and Scala's flexible method naming which, IMHO, make Scala both less abusable and more abusable.
In C++ the only way to get in-fix notation is using operators. Otherwise you must use object.message(argument) or pointer->messsage(argument) or function(argument1, argument2). So if you want a certain DSLish style to your code then there's pressure to use operators.
In Scala you can get infix notation with any message send. "object message argument" is perfectly ok, which means you don't need to use non-word symbols just to get infix notation.
C++ operator overloading is limited to essentially the C operators. Combined with the limitation that only operators may be used infix that puts pressure on people to try to map a wide range of unrelated concepts onto a relatively few symbols like "+" and ">>"
Scala allows a huge range of valid non-word symbols as method names. For instance, I've got an embedded Prolog-ish DSL where you can write
female('jane)! // jane is female
parent('jane,'john)! // jane is john's parent
parent('jane, 'wendy)! // jane is wendy's parent
mother('Mother, 'Child) :- parent('Mother, 'Child) & female('Mother) //'// a mother of a child is the child's parent and is female
mother('X, 'john)? // find john's mother
mother('jane, 'X)? // find's all of jane's children
The :-, !, ?, and & symbols are defined as ordinary methods. In C++ only & would be valid so an attempt to map this DSL into C++ would require some symbols that already evoke very different concepts.
Of course, this also opens up Scala to another kind of abuse. In Scala you can name a method $!&^% if you want to.
For other languages that, like Scala, are flexible in the use of non-word function and method names see Smalltalk where, like Scala, every "operator" is just another method and Haskell which allows the programmer to define precedence and fixity of flexibly named functions.
Operator overloading in C++ is
considered by many to be A Bad
Thing(tm)
Only by the ignorant. It is absolutely required in a language like C++, and it is noticeable that other languages that started off taking a "purist" view, have added it once their designers found out how necessary it is.
Operator overloading was never universally thought to be a bad idea in C++ - just the abuse of operator overloading was thought to be a bad idea. One doesn't really need operator overloading in a language since they can be simulated with more verbose function calls anyway. Avoiding operator overloading in Java made the implementation and specification of Java a little simpler and it forced programmers to not abuse operators. There has been some debate in the Java community about introducing operator overloading.
The advantages and disadvantages of operator overloading in Scala are the same as in C++ - you can write more natural code if you use operator overloading appropriately - and more cryptic, obfuscated code if you don't.
FYI: Operators are not defined as special functions in C++, they behave just like any other function - although there are some differences in name lookup, whether they need to be member functions, and the fact that they can be called in two ways: 1) operator syntax, and 2) operator-function-id syntax.
This article - "The Positive Legacy of C++ and Java" - answers your question directly.
"C++ has both stack allocation and heap allocation and you must overload your operators to handle all situations and not cause memory leaks. Difficult indeed. Java, however, has a single storage allocation mechanism and a garbage collector, which makes operator overloading trivial" ...
Java mistakenly (according to the author) omitted operator overloading because it was complicated in C++, but forgot why (or didn't realize that it didn't apply to Java).
Thankfully, higher level languages like Scala give developers options, while still running on the same JVM.
Operator overloading is not something that you really "need" very often, but when using Java, if you hit a point where you genuinely need it, it'll make you want to rip your fingernails out just so you have an excuse to stop typing.
That code which you've just found overflows a long? Yup, you're going to have to retype the whole lot to make it work with BigInteger. There is nothing more frustrating that having to reinvent the wheel just to change the type of a variable.
There is nothing wrong with operator overloading. In fact, there's something wrong with not having operator overloading for numeric types. (Take a look at some Java code that uses BigInteger and BigDecimal.)
C++ has a tradition of abusing the feature, though. An often-cited example is that the bitshift operators are overloaded to do I/O.
In general it is not a bad thing.
New languages such as C# also have operator overloading.
It is the abuse of operator overloading that is a bad thing.
But there are also problems with operator overloading as defined in C++. Because overloaded operators are just syntactic sugar for method calls they behave just like method. On the other hand normal built-in operators do not behave like methods. These inconsistency can be cause problems.
Off the top of my head operators || and &&.
The built in versions of these are short-cut operators. This is not true for overloaded versions and has caused some problems.
The fact that + - * / all return the same type that they operate on (after operator promotion)
The overloaded versions can return anything (This is where the abuse sets in, If your operators start to return some arbitrator type the user was not expecting things go down hill).
Guy Steele argued that operator overloading should be in Java as well, in his keynote speech "Growing a language" - there's a video and a transcription of it, and it's really an amazing speech. You will wonder what he is talking about for the first couple of pages, but if you keep on reading, you will see the point and achieve enlightenment. And the very fact that he could do such a speech at all is also amazing.
At the same time, this talk inspired a lot of fundamental research, probably including Scala - it's one of those papers that everybody should read to work in the field.
Back to the point, his examples are mostly about numeric classes (like BigInteger, and some weirder stuff), but that's not essential.
It is true, though, that misuse of operator overloading can lead to terrible results, and that even proper uses can complicate matters, if you try to read code without studying a bit the libraries it uses. But is that a good idea? OTOH, shouldn't such libraries try to include an operator cheat sheet for their operators?
I believe EVERY answer missed this. In C++ you can overload operators all you want, but you can't effect the precedence with which they're evaluated. Scala doesn't have this issue, IIRC.
As for it being a bad idea, besides precedence issues, people come up with really daft meanings for operators, and it rarely aids readability. Scala libraries are especially bad for this, goofy symbols that you must memorize each time, with library maintainers sticking their heads in the sand saying, 'you only need to learn it once'. Great, now I need to learn some 'clever' author's cryptic syntax * the number of libraries I care to use. It wouldn't be so bad if there existed a convention of ALWAYS supplying a literate version of the operators.
The only thing known wrong in C++ is the lack of the ability to overload []= as a separate operator. This could be hard to implement in a C++ compiler for what is probably not an obvious reason but plenty worth it.
Operator overloading was not a C++ invention - it came from Algol IIRC and even Gosling does not claim it is a bad idea in general.
As the other answers have pointed out; operator overloading itself isn't necessarily bad. What is bad it when it is used in ways that make the resulting code un-obvious. Generally when using them you need to make them do the least surprising thing (having operator+ do division would cause trouble for a rational class's usage) or as Scott Meyers says:
Clients already know how types like
int behave, so you should strive to
have your types behave in the same way
whenever reasonable... When in
doubt, do as the ints do.
(From Effective C++ 3rd Edition item 18)
Now some people have taken operator overloading to the extreme with things like boost::spirit. At this level you have no idea how it is implemented but it makes an interesting syntax to get what you want done. I'm not sure if this is good or bad. It seems nice, but I haven't used it.
I have never seen an article claiming that C++'s operator overloading is bad.
User-definable operators permit an easier higher level of expressivity and usability for users of the language.
However, it wouldn't seem to be qualitatively different to the operator overloading in C++, where as I recall operators are defined as special functions.
AFAIK, There is nothing special in operator functions compared to "normal" member functions. Of course you only have a certain set of operators that you can overload, but that doesn't make them very special.