I’ve been studying a lot of languages lately, looking for a modern, parallel language which is a deserving successor to C/C++/Python as my main, go-to language for Getting Things Done. Someone on Reddit was specifically asking why C++ isn’t ideal any more, and I wrote up this response based on my research. So, I thought I’d repost it here, too.
Let’s get right into what’s wrong with C++, then, and why I’d sooner replace it.
a) OO with class hierarchies is a broken model. Traits/interfaces with UFCS (aka extension methods), or even just structures with plain old functions and namespaces, is a MUCH better, more flexible approach that leads to better, more maintainable code. You only have to consider that, traditionally, a method is a function which REQUIRES a class within a hierarchy as the first argument, to realise that this is true. There’s a reason why modern languages (D, Rust, etc.) are doing this, rather than following C++’s model. Dijkstra said:
Object-oriented programming is an exceptionally bad idea which could only have originated in California.
Lately, I think he was right all along. But even out of those old-style OO approaches Dijkstra was talking about, C++ implemented it poorly, with diamond inheritance issues, virtual inheritance vs. normal inheritance issues, lack of an override keyword until recently, etc.
b) Algebraic datatypes and pattern matching have been around for years, and have clear advantages, both in terms of expressive power, and code reliability. If your language doesn’t support them, it sucks. For anyone unfamiliar, ADTs with pattern matching are like tagged unions and a switch statement to check the values in C++. Except, where the compiler can only check that all cases are matched in C/C++, ADT-supporting languages can unpack data structures, check the fields inside, and check that you’ve handled each case, without leaving something out — even across recursive functions. They’re called algebraic types because the language understands the rules behind the types.
c) Parallel programming has been around for years, and is becoming CRITICAL for modern applications. If your language doesn’t EASILY support it, it sucks. For example, dealing with threading and locking and worrying about safely sharing data between threads is EXTREMELY low-level, compared to other languages. A number of languages now will manage multiple OS threads for you, multiplex many green threads on top, manage a very small per-thread stack by default and grow it as necessary, manage communication between threads, etc., all with convenient, built-in syntax. Some languages will also do parallel loops with virtually no extra syntax, let you throw in closures, etc., while allowing that thread-based communication system to work with it. Some languages even check protocols between threads at compile time, making sure your threads don’t get out of sync or access pointers they shouldn’t access.
d) C++ has a RIDICULOUS amount of boiler plate. Compare Scala’s syntax for creating a class ctor, or Python’s syntax for it. Compare the inheritance of methods in python with C++ (constructors, for instance). Compare the deriving keyword in Haskell / the derive keyword in Rust. Compare the AST macros of languages like D, Rust, and Nimrod with C++’s macros and templates. C++ is LESS POWERFUL, LESS EXPRESSIVE, and WASTES YOUR TIME.
e) Headers shouldn’t exist in the language: modules should. The C++ committee acknowledges this, but won’t be getting it done until C++14, at least. Headers exist for a reason, but a modern language would work around these, handling definition loops and providing blackbox API definitions in other ways.
f) The same problems that make highly-parallel code (relative to other languages) a nightmare in C++ also make it an unsuitable language for security-critical, or mission-critical projects. There are just too many opportunities to introduce bugs which could allow someone to compromise the software (and then the server, and then the network, and then customer’s systems/services), and too many opportunities for bugs that could bring down a system in PRODUCTION. By contrast, languages like haskell and rust check your code MUCH more thoroughly at compile-time. Languages like D provide good support for design by contract, so you can catch your program at the function boundaries, if it ever behaves incorrectly.
C++ is loved for expressiveness, high-performance, flexibility, and strong type checking. Of those four, MANY languages do two (expressiveness and type-checking) MUCH better: D, Rust, go, etc.) A smaller, but still significant number of languages do those two better, AND compete strongly or even out-compete C++ on the other two. As languages, with real code, written idiomatically, Rust, D, and others will blow C++ out of the water, if you bear in mind that being able to easily write fast code matters, that being able to easily write parallel code matters, and that a LOT of time has been put into optimising C++ compilers, which is not indicative of the language, but the focus of those involved with it. By now, anyone sane should be looking elsewhere for future planning, even if they find themselves still using C++ for legacy reasons.