My Kingdom for a C+ Compiler!
January 23rd, 2007
Let the ranting begin…
This is probably the eighth time I’ve written a vector.h. Why so many rewrites, you ask?
Because it’s taken that long for me to divorce myself from C++’s second plus. A brief history
of our rocky little relationship, as recorded in the revision logs of my math utility files
(and written in third-person, because that amuses me), follows:
Revision One: Phill meets C, who introduces him to her sister C++. He is immediately smitten with her charming operators and her tight, expressive form. He goes home and does what he always does when he learns a new language. He sees how cool of a
vector.hhe can put together. He thinks to himself:template< unsigned int n > struct vector { /* some constructors */ /* some assignment operators */ /* lots of overloaded math operators */ } template< unsigned int n > float length( const vector< n > &v0 ); //and so onThe sudden realization that he’s just written
vector2,vector3andvector4all at once is too much to handle…he goes and takes a nap.Revision Two: Phill likes the way HLSL looks. He wanders off into
vector.hand starts typing stuff to make the C++ code look more like that. Constructors are constructed. Operators are operated on. Goodness abounds. Phill is so happy he sets his desktop wallpaper to a picture of a beach, codes some more, exhausts himself and takes another nap.That night he dreams of
vector::vector( float f )which initializes each of the vector’s components to the value offand allows pretty code likevector3 v = 0.Revision Three: Phill wakes up energized and ready to code. He starts writing…a program. Because he hates to reinvent the wheel (except where
vector.his concerned) he brings in some existing code. Said existing code happens to be written in C (whom Phill still talks to every now and then), and uses atypedef float vec3_t[3]for its vectors.Phill is getting rather sick of typing
vector3( v[0], v[1], v[2] )every time he needs to initialize a vector quantity. He quickly puts together some conversion operators to translate betweenvec3_tandvector3.The astute reader will note that the seeds of a really nasty bug have just been sown…
Revision Four: Phill runs the program and it takes ages to load. Confused, Phill pulls out a profiler and tracks down the offending code. It seems that the
vector::vector( void )which initializes the vector to zero is makingstl::vector’s various resizing operations take ages to complete. Irritated, Phill rips out the offending constructor; he replaces it with an empty one.Program behavior has just been altered in a fundamental way. Let the hunting for uninitialized variable bugs begin…
Of course, debug builds are still unbearably slow - but it’s easier to blame it on the STL than on the shiny templated vector class. And could someone please explain why the compiler won’t allow the vector type into a union…the default constructor is empty…I mean come on!
The magic is wearing off; the tropical beach has been banished from the desktop.
Revision Five: Sick of typing
vectorall the time, Phill renames it tovec. Find and replacevector=>vec. Whoops. Find and replacestd::vec => std::vector. Fix the files that started withusing namespace stdby hand.Phill reminisces about good times had, and wonders why C++ doesn’t make him smile any more.
Revision Six: A rarely-executed code branch suddenly reappears like an unwanted in-law coming to visit. It executes. The program crashes in
vec::vec( const float* ). One line up the call stack we find the linevec v = 0. Phill is confused until it hits him that a literal0casts more easily to afloat*than to afloat.He dies a little on the inside, but he’s determined to make this work. He goes through the code and replaces
= 0with= 0.0F.The magic is gone.
Revision Seven: More confusion. This time it’s in overloaded operator land. It seems the compiler can’t choose between two equally good conversions. Of course, Phill doesn’t expect the compiler to understand that it doesn’t matter which conversion it uses. He just wishes C++ would let him tell it.
Phill’s thinking of just calling the whole thing off. It’s just that he doesn’t want to abandon the new program (even though it’s talking back an awful lot these days).
Revision Eight: Phill’s finally had it. The impossible battles with overloaded functions, the slow debug builds, the ceaceless whining from the compiler…
Phill trashes
vector.hand copies in his original C version. He then renames the math functions to things likeoperator +because that’s pretty much the only thing that didn’t break or become annoying.The constructors become a set of functions:
vecNcwhich takes a set of literal float values (and a few unambiguous overloads involving vectors of fewer elements) and returns avecN.vec::vec( float* )becomesvecNv.It’s a painful transition but it works and for the first time the fuzzy sense of magic has been replaced with a concrete understanding that this line of code does this. The code size drops noticably as dozens of types that never needed constructors (but got them anyway because they had a
vecin them) start to compile into something sane again. It turns out that the STL was only responsible for about 25% of the debug-mode slowdown. The rest was all abusive constructors doing evil things.Epilogue: Phill and C++ have since gone their separate ways, deciding that it would be better if they were just friends.
And don’t even get me started on the awful inbred mess of of a multiple inheritance implementation that C++ seems to be stuck
with. Or all of the countless portability issues. Or the annoying…er…</rant>
The really irritating part is that in any serious project you pretty much can’t just take one plus and not the other. You can make
all the rules you want, but if you’re compiling with a full C++ compiler someone will eventually come along and put a constructor
in some little utility type that’s used everywhere, or use multiple inheritance, or make obscenely complex templates that nobody
can figure out (often not even the compiler). Sooner or later you’ll even see a dynamic_cast in there. And then there’s nothing you
can do but rename all the .cpp files to .c and fix the compiler spam.
I’d kill for some compiler switches, or even easy-to-grep-for #pragma directives, to turn off some of the more troublesome C++
features. Seriously, my kingdom for a C+ compiler…
2 Responses to “My Kingdom for a C+ Compiler!”
Sorry, comments are closed for this article.
January 24th, 2007 at 06:59 PM
Ahh the sordid, unsavoury world of coding… have you checked for STD’s (symantically transmitted diseases)?
January 24th, 2007 at 07:03 PM
DJ Phil ftw