I spent a little time yesterday reading through the changes to C++11.
Now, mind you, I’ve written a lot of code in C++, upwards of half a million lines of it: So I know all the intricacies of templates. I can use references and pointers safely. I can write const-correct code and overload operators without causing trouble. I know which parts of the language are sturdy and which are dangerously unsafe. I know how to aim the gun right next to my foot without actually striking it.
Now, I spent the last four years in C#, and that’s colored my opinions a bit. A lot of the stuff I used to have to work hard on in C++ is stupid-crazy-easy in C#, and not having to worry about freeing memory makes certain algorithms a few bajillion times simpler. But at the same time, I miss being able to control what winds up on the stack and determine where my memory gets allocated and when it gets freed. C++ gave me power, and sometimes I miss it.
So I think I’m at least somewhat qualified for talking about C++. And I went back to that language for the first time in a while yesterday and read up on what’s new.
I threw up in my mouth more than once.
C++ was unpretty the day I first learned it. — That said, C is a pretty language: C is simple and clean, with very few unnatural corner cases, and it has very little pretense at being anything other than steroid-infused semi-portable assembly language. Denis Ritchie knew what he was doing when he designed it, and the ANSI flavor (minus trigraphs) is a pretty clean design. It’s fast, it’s stable, and it does what it says on the tin almost always.
But C++ — man, that project got out of control fast. It was at first a clever extension to C, and it still stands in history as the first real proof that object-oriented languages don’t need to be slow. But there were so many weird corner cases that began to appear, so many seams where the thing began to unravel. The ugly and inefficient stream I/O. The hidden vtable, so you couldn’t do RTTI. The most vexing parse. Syntactic hacks to make certain declarations work. The awkward enforced separation between class declarations and their member function instantiations. The strange syntax of templates that wasn’t properly implemented for years. The discovery that that strange syntax was itself a full Turing-complete programming language. Copy constructors. Placement new.
By the time I stopped doing a lot of C++ four years ago, the language was a godawful mess, and the standards committee had utterly failed with C++03 to do much about it.
And so rather than fix so many of its most glaring errors and weirdnesses, they just bolted on more stuff in hopes that they could shout, “Hey, we’re a modern language too!”
So now it has lambdas. Lambdas are awesome, and so is the calculus and the Lisp that spawned them. But C++’s lambdas would make a Common Lisp programmer cringe: [&baz](const foo &f, const bar &b) { return f + baz + b; }
Functional programming is the new hotness. So C++ now has a function-declaration syntax that looks like it was stolen from ML, because apparently Ritchie didn’t know what he was doing when he put the return type at the beginning and the parameters in the parentheses. Seriously, check this example from Wikipedia:
template<class Lhs, class Rhs> auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}
And there’s type inference, because after typing std::x<y> forty-seven times in a single declaration and getting no actual work done, you don’t want to have to do it again.
And let’s add another “standard” regex library, because the 98 free libraries that you can download aren’t enough.
And don’t forget to download Boost! You can’t write real C++ without another few hundred thousand lines of libraries to manage your arrays and pointers for you!
When did C++ get so out-of-hand? Once upon a time, it was C, with classes. Neither more nor less complicated than that. It had C for getting stuff done and classes for keeping the stuff organized. Its current wranglers seem so intent on turning it from C-with-classes into a sophisticated exercise in type theory that the language no longer seems to actually do anything. In C, you can’t write more than a few lines of code without writing a line that at least does something — it computes something, performs an operation, moves some data around, crunches some numbers. In C++, you can write — quite literally — thousands of lines of template classes that do absolutely nothing whatsoever but push types around without ever getting around to actually, y’know, solving a real-world problem. Even in a language like SML where you’re spending all day every day on functional pattern matching and type theory, you’re still bound to cons a few list cells every once in a while. C++ is the only language I’ve ever seen where the boilerplate seems to be more critical to the language designers than the programs written in it.
So, grumble.
I’ll still use C++ from time to time, but I really think I’m going to keep eschewing the std:: libraries and the nightmare that templates have begun and focus on the basics: Use C to move stuff around and do real computation, and use classes to keep it all organized. And that’s really all that C++ ever should have been.