Hot answers tagged

118

In short, there aren’t any particularly useful subtraction-like operations on strings that people have wanted to write algorithms with. The + operator generally denotes the operation of an additive monoid, that is, an associative operation with an identity element: A + (B + C) = (A + B) + C A + 0 = 0 + A = A It makes sense to use this operator for ...


38

Because concatenation of any two valid strings is always a valid operation, but the opposite is not true. var a = "Hello"; var b = "World"; What should a - b be here? There's really no good way to answer that question, because the question itself isn't valid.


29

Abstraction 'hides' code so you don't have to be concerned about the inner workings and often so you can't change them, but the intention was not to prevent you from looking at it. We just make assumptions about operators and like Joel said, it could be anywhere. Having a programming feature requiring all overloaded operators to be established in a specific ...


28

Because the - operator for string manipulation does not have enough "semantic cohesion." Operators should only be overloaded when it is absolutely clear what the overload does with its operands, and string subtraction doesn't meet that bar. Consequently, method calls are preferred: public string Remove(string source, string toRemove) public string ...


17

IMHO, language features such as operator overloading give the programmer more power. And, as we all know, with great power comes great responsibility. Features that give you more power also give you more ways to shoot yourself in the foot, and, obviously, should be used judiciously. For example, it makes perfect sense to overload the + or the * operator ...


9

In Haskell "+", "-", "*", "/" etc are just (infix) functions. Should you name an infix function "plus" as in "4 plus 2"? Why not, if addition is what your function does. Should you name your "plus" function "+"? Why not. I think the issue with so called "operators" are, that they mostly resemble mathematical operations and there are not many ways to ...


8

The Groovy language does allow -: println('ABC'-'B') returns: AC And: println( 'Hello' - 'World' ) returns: Hello And: println('ABABABABAB' - 'B') returns: AABABABAB


6

A reference serves one purpose: to act as an alias for an existing variable: int i; int &ri = i; In this example, the addresses of i and ri are identical (&i == &ri). The two names refer to the very same location in memory. Thus one of the useful applications of references is to provide an alias for a long name that it would be wasteful to ...


6

The plus sign probably contextually makes sense in more cases, but a counter-example (perhaps an exception that proves the rule) in Python is the set object, which provides for - but not +: >>> set('abc') - set('bcd') set(['a']) >>> set('abc') + set('bcd') Traceback (most recent call last): File "<stdin>", line 1, in <module> ...


6

Based on the other answers I've seen, I can only conclude that the real objection to operator overloading is the desire for immediately obvious code. This is tragic for two reasons: Carried to its logical conclusion, the principle that code should be immediately obvious would have us all still coding in COBOL. You don't learn from code that is ...


6

The answer to your question is rather simple: Backwards-compatibility means not changing the meaning of existing code. Since there is no existing code using user-defined operators, because user-defined operators do not exist, introducing them cannot possibly break backwards-compatibility. Foo a = new Foo(); Foo b = new Foo(); Foo c = a + b; Such code ...


5

What about creating a class to hold your arguments? This class would contain both open and close parameters and either of them could be NULL. Then, there will be only one strip method with above class as argument and method will decide if it wants to use open/close if they are set.


5

I somewhat agree. If you write multiply(j,5), j could be of a scalar or matrix type, making multiply() more or less complex, depending on what j is. However, if you abandon the idea of overloading altogether, then the function would have to be named multiply_scalar() or multiply_matrix() which would make it obvious what's happening underneath. There's ...


4

I see two problems with operator overloading. Overloading changes the semantics of the operator, even if that is not intended by the programmer. For example, when you overload &&, || or ,, you lose the sequence points that are implied by the built-in variants of these operators (as well as the short-circuiting behaviour of the logical operators). ...


4

Despite "I'm not considering static methods, just operators", the statement immediately before it suggests you are asking for a static operator(). If this were possible, the most vexing parse would be much more vexing! Upon further inspection, it reads like you are basically in the market for a static function. The whole purpose of operator() is to make a ...


4

An "overloaded" function has to be polymorphic, because it's impossible to write a class constraint unless the function signature already contains a type variable. Based on this, I wouldn't say that overloaded is a very useful concept in Haskell.


4

There are many options, it's your tradeoff which to take: Decision at runtime: Add a defaulted bool argument: QString MyClass::strip(QRegularExpression regex, bool close=false); // Mimic the two-regex-variants interface as good as possible Use scoped enum's and no default as a variant on 1 which is more descriptive: enum class option { open, close }; ...


3

I would suggest QString MyClass::strip(); QString MyClass::strip(QRegularExpression regex, bool opening=false); QString MyClass::strip(QRegularExpression open, QRegularExpression close); and perhaps QString MyClass::strip_open(QRegularExpression regex); QString MyClass::strip_close(QRegularExpression regex); or replace the bool opening with e.g. enum ...


3

"-" is used in some compound words (for example, "on-site") for joining the different parts into the same word. Why don't we use "-" for joining different strings together in programming languages? I think it would make perfect sense! To hell with this + nonsense! However, let's try looking at this from a bit more abstract angle. How would you define ...


3

This doesn’t answer the question definitively, but the earliest use of it I can find is from John Peck, recalling a meeting about the Algol standard in Warsaw in 1966: “What I can remember of that meeting was the insistence of John McCarthy, that any new language should have what he called overloading of operators. This would eventually became the operation ...


2

One difference between overloading a * b and calling multiply(a,b) is that the latter can easily be grepped for. If the multiply function isn't overloaded for different types then you can find out exactly what the function is going to do, without having to track through the types of a and b. Linus Torvalds has an interesting argument about operator ...


2

I think that overloading math operators is not the real issue with operator overloading in C++. I think overloading operators that should not rely on the context of the expression (i.e. type) is "evil". E.g. overloading , [ ] ( ) -> ->* new delete or even the unary *. You have a certain set of expectations from those operators that should never change.


2

I suspect it has something to do with breaking expectations. I've you're used to C++, you're used to operator behavior not being dictated entirely by the language, and you won't be surprised when an operator does something odd. If you're used to languages that don't have that feature, and then see C++ code, you bring along the expectations from those other ...


2

I perfectly understand you do not like Joel's argument about hiding. Me neither. It's indeed much better to use '+' for things like built-in numerical types or for your own ones like, say, matrix. I admit this is neat and elegant to be able to multiply two matrices with the '*' instead of '.multiply( )'. And after all we've got the same kind of abstraction ...


2

Technically, there are not much differences between variable of type int* and int& (except those syntactical details about dereferencing and member access). The main difference in practical use IMHO is that you cannot change the object a reference is refering to after initializiation (while you can change the adress a pointer points to), and a reference ...


1

The easiest way to limit the combinatorial explosion of your overloads is to introduce a small helper class that can accept all the various types and convert them to a single common type. For example class FileHelper { public: FileHelper(HANDLE& h) : handle(h) {} FileHelper(const TCHAR* fName) : handle(openFile(fName) {} FileHelper(const ...


1

A reference is another name(alias) for an existing object; it gives you the power of "pass by reference" and the convenience of using it like you would the object itself. In your example, the address of ri and i are the same and the values of each are the same. How the compiler handles this is another topic, but it really does boil down to my first sentence....


1

Technically speaking, references are not objects and you cannot reason about their contents. However, in reality, as pointers under the hood that's how they're often implemented. As for the function declaration/definition, they are not operators. They are syntax. int& is a type. It means "I return a reference". Returning an int& isn't any different ...


1

In comparison to spelled out methods, operators are shorter, but also they don't require parentheses. Parentheses are relatively inconvenient to type. And you must balance them. In total, any method call requires three characters of plain noise compared to an operator. This makes using operators very, very tempting. Why else would anyone want to this: cout &...



Only top voted, non community-wiki answers of a minimum length are eligible