Best C++ - Bashing code?

Hi,

this' topic probably existed numerous times before, but I'm in good mood and start a thread again anyway. :-)


What's your favourite code that shows why C++ sucks hard?

I throw this one in (from Fefe: http://www.fefe.de/c++/c++-talk.pdf)
1
2
template<class T> struct Loop { Loop<T*> operator->(); };
Loop<int> i, j = i->hooray;


Ciao, Imi.
Well, at least it was a better read than the FQA, which was quite obviously written by a Javatard.
I think that this 'Javatard' is actually right in some cases. C++ is far from being perfect, although it is still the language I use the most.
FQA? Javatard?
Interesting article, was it written by Mrs Palin?

Any technology can be abused and this article is all about abusing C++, not about using it correctly.
closed account (S6k9GNh0)
I agree. I hate when people go on about ways to use a language incorrectly and then call the language bad based on those uses. It's rather irritating to be honest.
I really don't get it, what is the deal with this code:
1
2
template<class T> struct Loop { Loop<T*> operator->(); };
Loop<int> i, j = i->hooray;
?

Can anybody explain?

i->hooray should be (i->()) hooray, which should be a syntax error. Where is the infinite cycle here? Where am I making a mistake?
It's hard to explain, but what happens basically is that the compiler ends up adding new instances of Loop<T> to the symbol table forever with a forever increasing amount of indirection. This code makes whoever thought of it, an n-star programmer.
The compiler doesn't even reach 'hooray' because it's busy figuring out what Loop::operator->() is supposed to return.
It's not for nothing that C++ templates are said to be Turing-complete.
Last edited on
I don't want to start a war here, but you guys are too fast dismissing that article (I mean FQA).

I will give you only one example.

Charge: #include is far inferior to an import capability present in many languages (Ada, D, etc.). One of its disadvantages is that the compiler needs to parse megabytes of text even for very simple programs, what results in a compilation process being slow. Tell me, where exactly do you see 'abusing' here? I'm not supposed to use #include?
Which is why precompiled headers exist.
Although why the standard headers aren't distributed in some sort of an intermediate form aside from plain text that allows the compiler to obviate parsing them, is not a bad question.
About the pdf:

I think I saw about 3 valid things in there, most of the others were random, irrelevant, or abusive (like the template thing, why would you *ever* write that?).
Precompiled headers, hmmmm... And we came to another defect - lack of compatibility between different compilers ;)
Last edited on
@firedraco

Are you trying to suggest that:
1) Error reports for template code are not a total mess?
2) Template metaprogramming, expression templates, etc. are not a total mess?
3) Template metaprogramming, expression templates are not very unlikely to work on a different compiler?

The above statements are intentionally exaggerated :)
I think I saw about 3 valid things in there, most of the others were random, irrelevant, or abusive (like the template thing, why would you *ever* write that?).

Ohman, guys.. relax. The talk was funny. Why you all are so serious about this? Am I strange that I can laugh about crazy code like the template recursion?

Actually I wanted to start a thread with replies like: "You call this bad? *yawn*. Watch this and bow: " and the some really ugly things that could make it into IOCCC, only its in C++.

Or some funny anecdote about a thing in C++ that made you wish it has never been invented. :-D. You surely know some, do you? (Something obviously "not a function" is still interpreted as "function declaration" would come in mind ^^)


Ciao, Imi.
<whisper mode>
Imi, please don't. You ruin my plan to detect who on this board acts as an expert, but actually doesn't know anything beside C++. Such people tend to defend their favourite language as if they would fight for their lives.
</whisper mode>
It's hard to explain, but what happens basically is that the compiler ends up adding new instances of Loop<T> to the symbol table forever with a forever increasing amount of indirection. This code makes whoever thought of it, an n-star programmer.


I still don't get it. So, are you saying,

i->operator() returns Loop<int*>, on which you evaluate

(i->operator())->operator() which returns Loop<Loop<int*>*> on which you evaluate

... and so on infinitely long.

Well, that is all cool, but why the hell on the second step you evaluate (i->operator())->operator()? The operator ->() shouldn't be replicated in the above infinite process. It should appear only in the first recursion step, and then crash out with bad syntax/
tition: to determine the type of the expression "i->hooray", the compiler has to determine the type for "*i". Since i appears in a "class member access" - expression, it uses *(operator->()).

The type of operator-> is not a plain pointer, so it tries to dereference it by using operator-> again. This time on the return of the original operator-> which was Loop<int*> (not to be confused with Loop<int>*).

So it looks at the return of Loop<int*>::operator->() which is Loop<int**>. Still not a pointer, so it uses operator-> again to obtain the dereference (this is still possible as long as we want to evaluate a class member access).

In the next step you get Loop<int***>, which is not a pointer...

and so on.


I could imagine, that the behaviour of this postfix expression evaluation was made to make it possible to implement perfectly transparent smart pointer (anyone? Was this the reason?). Consider the following:

1
2
3
4
5
6
7
8
9
10
struct A { int i; A():i(42){} };
struct B { A* operator->() {static A a; return &a;} };
struct C { B operator->() {return B();} };
struct D { C operator->() {return C();} };

int main()
{
	C c;
	cout << c->i;
}


B, C and D are "perfect transparent" smart pointer (well, not really. As *c won't work nicely. But that's another story. They are transparent when it comes to c->i.)


If you want to read up more about the postfix expression, it's in the standard chapter 3.2.4 (for the parsing stuff) and 5.2.5 (for the class member access evaluation.)

Ciao, Imi.
I get it, thanks!

Well, the above problem wouldn't occur if overloading operator-> wasn't allowed. On another note: why is overloading operator-> allowed? What is the practical use of overloading ->?

like the template thing, why would you *ever* write that?
The point of the example was that C++ was hard to parse, which it certainly is. Some have said that its syntax is undecidable.

Precompiled headers, hmmmm... And we came to another defect - lack of compatibility between different compilers ;)
And pray tell, why would you need to use the precompiled headers generated by one compiler, on another compiler?
Precompiled headers are a tool to reduce compilation time for a particular build. They aren't libraries.
What about digraphs that could complicate template code?

(* = {

*) = }

Are these still supported?

Last edited on
Topic archived. No new replies allowed.