- Feature Articles
- CodeSOD
-
Error'd
- Most Recent Articles
- Stop Poking Me!
- Operation Erred Successfully
- A Dark Turn
- Nothing Doing
- Home By Another Way
- Coast Star
- Forsooth
- Epic
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Can I assume that the * characters in the loop line were not there in the original code. It doesn't make sense this way.
Admin
Ah yes, ban all features that can be abused. I hope they outlawed pointers, multiple inheritance, operator new and templates too. Maybe they should just switch to Java if their programmers aren't competent enough to handle C++.
Admin
getNextNode() doesn't take any parameters, so what does CFNode + 2 do? I'd assume it does CFNode.getNextNode().getNextNode(), but wouldn't be surprised if it did the same thing as CFNode + 1
Admin
Unfortunately it makes perfect sense.
for (CFNode* nptr = *firstPtr + 1; *nptr + 1; nptr = *nptr + 1)
First * denotes a pointer to CFNode. All remaining *'s dereference the pointer and run the overloaded operation, which returns a pointer.
Admin
I don't have a clue what is going on :( It has been too long since I did C++.
I was going to say I hope Sun ignores the people asking for operator overloading in Java, but, without pointers, if it is restricted to the numeric operators it could be ok (no == overloading etc.).
Admin
Admin
Ah yes, of course. Thanks ! Makes it even worse....
Admin
This overloading is a case of a smart person being overly "clever". Hence they probably thought of that scenario and it would return getPrevNode()
Admin
Well there is a getPrevNode(), for negative values.
I'm not sure the poster's logic "Knowing that almost every pointer value plus 1 will result in a non-NULL pointer" makes sense. Since it's a pointer to a class, you don't automatically know WHAT the pointer value plus 1 will equal. The correct objection is that CFNode + integer = pointer, which is not the way arithmetic operation usually work.
Admin
I think that WTF is not that someone overloaded operator+ for CFNode and int. It still sematically makes some sense to recceive 'n-th neighbour of current node'. The WTF is that s/he made operator+(CFNode, int) return pointer to CFNode, or made CFNode class implicitly convertable to bool.
Admin
In one of my CS classes a few years back, we were taught that this was the standard method of handling iterators.
Of course, I haven't programmed in C++ since then, but still;
Admin
it's been forever since i've done c++ so if there are small syntax typos forgive me :-) my guess is the function is defined:
Admin
Admin
Overloading operators is fine, as long as the overloaded operators have the same semantics as the default operator, or some other clear meaning (like operator+ for string concatenation). Here this clearly is not the case - adding an int to a CFNode makes no sense, especially since the value of the int is ignored, and it does not even return a CFNode, but a pointer to one shudder. And I can't help but wonder, why isn't one of the standard STL containers used for something that is clearly some form of linked list?
I'd say the coding standard should be: Be prudent with operator overloading, yes, but don't ban it completely - it has its place. And use STL wherever possible.
Admin
oops, "this" is already a pointer in c++ (as opposed to java), hence change "&this" to simply "this"
Admin
They'd better ban (naked) pointers, not a language feature.
Admin
The first thing I thought was "No! They should've overloaded the increment operator! That makes much more sense, because then you can iterate through a list of nodes like you can through an array." I haven't worked that much with C++ (although I master it rather well) because in other languages things get done faster, but even that limited exposure has apparently infected me with the disease.
Admin
Admin
the standard what? Yeah, all this would never have happen. At least he did not inherit from a std::vector though...
Admin
Admin
Really, operator overloading is so rarely useful and so often harmful that banning it entirely is a sensible idea.
Admin
Its easy to understand the danger in operator overloading... but for the c++ impaired among us can someone please explain exactly WTF is going on here?
Admin
We should ban cars too. Too many people are in car accidents. And fatty food. And alcohol. And tobacco. And airplanes. And sugar. And....
While operator overloading is often misused, that's the power of C++. You can do pretty much whatever you need to and don't have to worry about limitations of the language. That said, you can also easily blow your entire leg off with it but just because something has the potential to be dangerous doesn't mean it should be banned outright.
Perhaps in this particular case at this company, operator overloading should have been banned but that's definitely a case by case basis.
Admin
It's sort of like Java's half-assed approach to multiple inheritance. There is no multiple inheritance in Java - except through interfaces.
Let me guess, you're in the group that thinks that Java not including unsigned variables is a good thing?
This example of operator overloading is a WTF, but there are plenty of instances where it can make code more readable and does make sense. String comparison and concatenation is one of the classic examples - very infrequently do you want to know if two strings use the same reference, and if you ever do, you can just cast them to (void*) to check anyway.
Admin
If you want operator overloading in Java use Groovy as it has a lot of other syntax sugar you would probably want also.
Admin
Let's ignore the red herring of the overloaded operator (which is actually operator+(), but I know what you mean) for a moment, shall we? After all, it's just syntactic sugar -- or in this case, syntactic cyanide.
Replace that with the (supposedly) equivalent member function, and you have:
... at least, I think you do. Even trying to rationalise this makes my head hurt.
... and I had to rewrite the rest of this comment, based upon substituting the member function.
How the hell is a maintenance programmer supposed to guess what's going on here?
This code is still bizarre. Why check that the next node is "false" (one has to hope that the end of the list is specified as NULL) and then go ahead and assign it to nptr anyway?
I don't see pointer arithmetic on a NULL anywhere here (perhaps I'm short on caffeine), but why not use the STL? Or at least iterators? Or possibly a good, old-fashioned for-loop in C that makes sense?
The guy who wrote this should be taken out back and forcibly re-educated, with a pointy stick. The fact that it misuses features of the C++ language is entirely besides the point.
The while-loop just adds to the insanity.
Admin
As a former C++ coder, I tended to judiciously use operator overloading where it made sense. Unfortunately, I inherited an 800K+ LOC mess, where the authors believed that you should use every conceivable feature of C++, whether it made sense or not. After much debugging and banging of head on desk, I discovered the following in a deeply nested hierarchy:
overload >> to write to database and return what was written overload << to read from database overload > to write to stream overload < to read from stream overload [] to read the nth record from a stream/result-set overload ++ to implicitly create a new version of the transaction in the db (version=version+1)
The << was particularly annoying as innocent calls to cout would start hitting the db and loading the stored version of the object instead of the one you were trying to print - it drove me nuts trying to figure out why the variable I had just set seemed to still have the old value from the db - the debugger showed the correct value but cout showed the old value (from the db).
The guy who wrote it had moved on to another team - I hunted him down and publicly ripped him a new one.
For the record, to make it easier to understand what the thing was doing I replaced all the overloaded operations with descriptively named functions. At least new team members could follow what it was doing.
Admin
Admin
Banning operator overloading is stupid. C++ is limited enough as it is, without intentionally ignoring its feeble attempts try to act like a real programming language.
That said, I probably would require that coder in future to go through code reviews on all their submissions with someone who knows their head from their ass (or at least their arithmetic types from their pointer types).
Another commenter suggested allowing only arithmetic operator overloading, not boolean or other operators. This is stupid as well. You need to overload pointer and equality operators to design classes that can replace standard pointer types. You need inequality operators to implement sorting or ordered containers. You need to overload function operators to use templates or generics. You need to overload bitwise-boolean operators to implement set union/difference/intersection operations. You need to overload type conversion operators for, well, type conversions. And so on...
About the only operator that you never need to overload is the comma (",") operator.
Admin
So multiplying matrices would be one of those "rarely useful" instances where you would use it.
You people really do have an unhealthy love affair with your language features don't you?
Admin
Part of me sympathizes with your pain. Really.
Another part of me wonders...
how the hell did he managed to arrange things so that "std::ostream &operator<<(std::ostream &, const T &)" gets replaced with "T operator<<(std::ostream &, DB &)" without a whole pile of ambiguous function call errors?
Admin
When I was first learning Java and just beginning to understand the concept of OOP I hit on a great idea to demonstrate objects by making a "measurement" class. The way I planned it, you would be able to convert from one unit type to another, and multiply those units so they would follow logical rules. For example: If I added two Length objects I'd get another length object; if I multiplied two Length objects together it would return an Area object; if you divided a Length unit by a Time unit you would get a Speed object.
So the code would look like this: maxHeight = myHeight + hatHeight cubeVol = h * w * d
This would be a perfect and perfectly logical use of operator overloading, particularly useful for use in, say, physics simulations (not that I had any illusions about this being used in any real context but that was the general idea). I was pretty disappointed when I found that you couldn't actually make it look like that, and instead had to use awkward methods like .plus(x). I maintain that operator overloading, if used properly, adds to the readability of the code, and I've always been annoyed that Java didn't support it.
Admin
Whenever there is a discussion about the merits and problems of operator overloading, its fans always come up with the same two examples: matrices and complex numbers. Do we really need a highly abusable language feature for the sake of two specific applications? The vast majority of software is not very math-intensive at all. Sure, if you do work on a math-intensive app, then anything that lets you code as close to the mathematical notation as possible looks like a gift from heaven, but even that is an illusion because all except the most trivial math needs far more symbols than there are appropriate operators in ASCII.
Admin
A particularly egregious example of operator overloading is in JavaScript, where the + operator serves for both numeric addition and string concatenation. While that is bordering on acceptable in a statically-typed language (such as BASIC, which is where I believe the practice originated), JavaScript is dynamically-typed. In other words, variables can be interpreted as numeric or string depending on context.
So you can get something like document.theform.users.value += 1 concatenating a figure "1" to the end of the text field, rather than incrementing the value.
I normally rewrite all additions in JavaScript as subtractions; it has no problem with document.theform.users.value -= -1 though it looks a bit strange at first glance.
Perl (the original dynamically-typed language) and its crazy bastard son PHP had the common sense to use a separate operator (the dot) for concatenation (although since all Perl and PHP variables begin with a $ sign and variables whose names are mentioned inside "double speech marks" get replaced with their values, this is redundant: one may write $name = $title . " " . $initial . " " . $surname as $name = "$title $initial $surname" with no ill effect).
Admin
OK, I'll bite: what is, in your opinion, a "real programming language"?
Admin
Banning a language feature because of a bad judgement call by a programmer ... especially something as basic and useful as operator overloading ... thats just absolutely, positively insane.
Mathematical operations on UDTs (matrices, quats, vectors, fixedpoint, complex), serialization, string operations, sort comparisons, equivalance-by-key, new/delete overloading for memory management...you want to return all of this (and so much more!) to C style function calls because someone, somewhere might overuse the language feature?
Are you people serious?!
I guess you should also throw out STL as well because in case you haven't heard it's actually requires operator overloading for many of it's most common containers.
Admin
(Actually, that neatly encapsulates my loathing of built-in "libraries" that people seem to think are actually part of their language these days, but no matter.)
There are, in fact, several other operators that should never be overloaded -- the ternary operator springs to mind, not to mention operator *->() -- but again, we're drifting from the point here, people.
This is rank, bloody awful code with or without operator overloading.
And please, please, let's get away from this juvenile language-war thing.
(Unless, of course, some kind soul wishes to "anonymize" the OP as VB6...)
Admin
Overloaded operators are rarely useful. 99% of the time, they're more trouble than they're worth, and they're not something anyone with less than two years' experience developing C++ with other human beings should attempt outside of a controlled academic setting.
The other 1% of the time, there's some problem domain that can be easily and readably solved by using a small set of functions, with particular relationships between their types, and the best possible names of those functions are +, -, *, &, <, >, !=, ...
Since we're stuck with the names and semantics of +, -, etc (which are fairly sophisticated--there's dozens of pages in the C and C++ standards that define exactly what "+" does and does not do without mentioning operator overloading even once), it follows that if we're going to get anything done in this language then we need to be able to redefine the behavior of the operators for non-trivial data types. This is a requirement for C++ and not a requirement for C, because C doesn't have non-trivial data types.
Arguably, C++ (and C, from which most C++ operators arise) has too many operators to start with. We wouldn't want to overload them if it weren't so much more convenient to use them on intrinsic types, or if the alternative function-call syntax wasn't so fugly and didn't have subtly different semantics.
Compare C++ with LISP, which has only a half-dozen or so operators (and that's really stretching the meaning of the word "operator"), no operator overloading, and a lot more expressive power than C++. In LISP, you can redefine the meaning of an entire expression, not just the operators used within it.
Admin
Admin
You should duck... now!
Admin
An overloaded operator is nothing but a function call that looks prettier. (You could imagine a language, where you don't have for example arithmetic operators, and have to use assign(n, add(x, y)) instead of n = x + y.)
Operator overloading abuse is no different than misnaming functions, both are just as easy to happen.
So, if someone would misname/misconstruct a function, you'd be happy to ban function usage? WTF!
Admin
Admin
Here's an experiment for you operator overloading haters - go back to one of your university math books and convert the largest equation you can find into prefix notation and then compare the readability to the original text.
Now imagine the entire book was written that way.
Admin
Actually, for matrix work I prefer to use overloaded functions. "Matrix add(const Matrix &M, const Vector &V)" can be overloaded with "Matrix add(const Matrix &M, const Matrix &M2)" and all the other supported combinations. To use it with some objects "V1" and "V2" you just write "Matrix M = add(V1, V2)" without caring what types V1 and V2 are.
In C++, I find operator overloading for iterator types essential. Usually I'm replacing a pointer type with a class type without changing all the code that used the pointer type, and the sematics of pointer operations are both well-defined (so I always know what operator *() does) and limited (anything outside of what C++ pointer operators can already do isn't pointer semantics any more by definition).
The other big use of operator overloading I use is for stream operations. This is really common for I/O tasks (such as streams, obviously) and for building data structures to be used by other languages where there is one and only one mapping from C++ datatypes to the other language (e.g. LISP and Tcl) and the data in question is mostly lists or trees of object values. It's not possible to do this with methods because in C++ you can't expand the set of methods on an object outside of the class declaration. Overloaded global functions are overly verbose and don't use infix notation, which severely hurts readability.
Admin
I spent a lot of time refactoring / rewriting that mess.
Admin
Don't worry about the ternary operator, you can't overload it (13.5.3 forbids overloading the operators . .* :: and ?:, and also mentions that # and ## are not really operators so you can't overload them either).
Hmmm...that would permit smart pointer-to-member classes (analogous to smart pointer classes, but they choose a member function for you instead of an object). That opens up entire worlds of polymorphism...
Admin
I'm not so sure about being the original (it could be) but it's certainly very good at it.
Also, the . operator is not redundant. Take, for instance:
Admin
I don't think it's such a big WTF actually. He just made his structure follow the C idea of null-terminated arrays. IIRC, in C, adding a number to a pointer to something, adds numbersizeof(something) to the pointer, making something and something[] the same types.
It is possible that "CFNode* operator+(const int rhs)" does the correct analogon of the pointer arithmetic. Or it contains
assert(rhs==1); /* implement pointer arithmetic here if needed */
I suggest to get a copy of K&R and look at the code examples in it. The code in the article looks to me like being perfectly in the spirit of K&R's strdup.
If there is a WTF, then it's the hacker tricks proposed by the inventors of C. Or the WTF is that people who don't know the roots laugh at stuff they don't understand anymore. Granted, it's 35 years old, but that's not a crime.
(I'd like to add some examples where operator overloading is nice, because I belong to those who write math-related code and think op overloading is the first thing we add to Java when the revolution comes: Game engines with specific gfx-card-friendly "3D vector" types. Critical financial systems where you don't want your $2^31 to become $-2^31. Computations with exact arithmetic. BigNumber packages.)
p.s.: The must stupidest thing IMO is that Java thinks that "+" must exist for int and String, but not for Integer. My last Java experience is a few years old, so: Is it still so that the result of (new Integer(1))+(new Integer(1)) is legal code and results in the String "11"?
p.p.s.: The real WTF is that the author thinks that NULL must be 0. Is not true.
p^3.s: My first WTF post. Yay.
Admin
As a matter of fact, this issue also exists with Java -- which was still a statically typed language last time I checked -- as the following:
prints `Do stuff 35`, since expressions are evaluated left-to-right, `"Do stuff " + 3` is evaluated first, so `3` is converted to a string and appended, and only then is the second addition performed.But things become much funnier when you get the expression
"Do stuff " + 3 * 5
. No it doesn't blow up, it prints"Do stuff 15"
, probably because the precedence for the "*" operator is higher than the addition.Please note that the very example you used against javascript gives exactly the same result in Java:
document.form.users.value
is of type string, Java will convert the "1" to a string and append it, go ahead and test it.Therefore the first part of your statement ("+" for both concatenation and addition is ok for statically typed languages) is plain and simply wrong.
Now let's look at the second one "but it's not ok for dynamically typed languages. Python is as dynamically typed as a language can be. Let's see how it behaves:
Cleary, Python has a perfectly sane behavior.The problem is not with using "+" for both number addition and string concatenation, the problem is with performing automatic coercion between strings and numbers when using the
+
operator.Admin
Real programming languages can generate, inspect, or modify existing code at runtime, including (within reason) the code of the language compiler and runtime library.
The biggest clue that you have a real programming language is that you can 1) write a function body in the argument list of a function, and 2) generate a function body by combining data passed as arguments. C++ can do both of these things with templates, but template code generation is only at compile time (unless your C++ program has a compiler and debugger hidden in a library somewhere), and is highly restricted even then (thanks to ISO C++ section 14.7.3, it is not possible to extend the set of available template specializations available to the arguments of a member template after the member template has been declared or instantiated, no matter how damn useful that capability would be in practice).
Another clue that you have a real programming language is that you can iterate over function bodies as you would any other data structures. C++ programs that can do this are called "debuggers" or "virtual machine emulators"--these capabilities are certainly not expected from standard C++ implementations. Real programming languages expect nothing less from their standard libraries.
Another sign is that the language is very small--a complete syntax description for most real programming languages fits on a single page--and just about every language feature is implemented by library functions (although often library functions are themselves just code generators, so you get the same machine code at the end whether you used "x+y" or "add(x,y)").
Templates and RTTI are about as far away from this kind of capability as Microsoft Word macros are from assembly-language programming.
Once a problem domain reaches a critical level of complexity, the only solution available to a C++ developer is to implement a real language in C++, then implement the rest of the solution in the real language. Most people fail when they try to do this, they fall victim to Greenspun's Tenth Law, and their code ends up here.