Why C++ sucks (2016.02 edition)

[I see a lot of people still read this article, with many of these faults addressed, really. I guess it’s time to make an update to this. It’s been a while.]

I see that there’s some interest around my „Day when I gave up on C++„. People on reddit discover this article of mine from time to time, and it’s somewhat boring to see the same things discussed over and over again.

To be honest, I don’t agree with my article, but I do agree with the points I’m making. I was very upset that day – it was yet another try to start a project when I had to work for two days for the basic setup only to see that things don’t work. After a set of frustrating cycles of try/find errors/search-for-solutions/try-again-with-something-else I just gave up on a project that is very dear to me. I don’t have the energy to fight with the language, even though I follow it closely. But it’s the same with advanced physics. Yes, neutrinos, bla bla bla, but does that make my car go faster? No? Ok,

I will just say one last thing about that article. It was written after I came to the conclusion that it was impossible to have graphics and a proper C++11 compiler working together. Not to mention a proper IDE – it was before Microsoft came around and fixed a few of the rough edges of their C++ IDE. There was no CLion. QtCreator was quite weak and buggy. Don’t get me started on people that thing that vim is a proper IDE – there were enough of these as well. So no, that day it was impossible for me to love C++. In a sense, it still is.

I will repeat that joke, though. What does the 11 from C++11 mean? The number of feet they glued to the octopus to make it a better. This is felt throughout the language, and today the first thing I suggest to people is to stop thinking that C++ is a superset of C. It is, but let’s forget that. That’s what Kate Gregory suggested a long time ago, and she made a kick-ass presentation at CPPCon about it((Sidenote: my girlfriend, not a programmer, really liked her presentation, she thought she was kick-ass)).

I’ll rehash a bit the ideas I had back then. I wasn’t that stupid, I just wasn’t offering the proper arguments. So let’s see:

C++ IDEs suck.

As of 2016 they still do. You can take each IDE and find incredible sucky points, but they all come from the same root cause – it’s not the complexity of the language, but from the fact that they try to offer too much or too little. The offer is quite big, I will make a simple list of things I don’t like „at a glance”

  1. Visual Studio: they made it a bit uglier, but they actually support C++17 (as much as they can). That’s amazing, but the IDE is still a pile of confusion when it comes to including an external library in your project. If I remember correctly, while they offer a standard C library it still matters if you compiled your library for multithreaded debug or for single threaded release. It’s hard to reference a library, it’s hard to deliver a library with your executable. You still have to deliver a runtime.
  2. CLion wants to be the big, smart guy in this area. I actually bought their IDE. I love it, it’s pretty fast, it’s neat, it’s responsive (except when it’s not). They only support cmake (and cmake is horrible, you can’t write proper modules without a lot of pseudo-coding in their funky language which I don’t care about and don’t want to learn). They don’t deliver a compiler that compiles stuff on the platform they deliver (they don’t have a MSys/Cygwin like system that actually works, I wish they would). They don’t support remote debugging.
  3. QtCreator is the IDE I really wanted to love. It’s focused, it is obvious that it’s inspired by the old Visual C++, the good one. It delivers its own tools, which is a plus. But you can’t create qmake projects if you have a cross compiler or you don’t have a Qt library in that toolchain, and qmake is the only sane way do projects (simple, without complex programming of features in strange languages. But limited and badly documented 🙁 ). QtCreator is, like CLion, an IDE I really really want to use, but it’s hard to when it suggests I should do manual steps in order to do what they could easily automate. I know, it’s open source and I can help improve it.
  4. Eclipse. Eclipse is huge and offers an amazing set of features, alongside lack of speed and yet another build system. If you go for an autotools project you simply forget that it has those features – it manages to hide all those features from you or forget that it has them. For example there’s no way to deploy and debug remotely if you use the autotools project. You have addins for everything, but it’s a moody system (for example it keeps forgetting my settings for the toolchain if I click on the wrong area, and it keeps forgetting that when I hit debug I really want to go on the remote platform because I use a cross compiler. Eclipse is not a C++ IDE, perhaps Java developers are more accustomed with tools that they can’t understand and they have to perform magic in order for them to work relatively appropriate.
  5. Netbeans. Faster than Eclipse, pretty much the same deal.
  6. KDevelop is getting worse and worse every year. In 2003 I was working on real, production projects with KDevelop, I wouldn’t entrust my code to KDevelop now.
  7. [Your favorite IDE here]. To put it plainly it sucks as an IDE (perhaps not as a glorified code editor). You can include here Code::Blocks, Vim, Emacs, SlickEdit, etc.

For each IDE there are a lot of points I could hit on. I chose the things that really make me hate them.

It’s a barely manageable language

I think that was one of those misunderstood points. My point was that there is no clear flow to work with the language. That can be a blessing, it allows a lot of freedom. That can be a curse. Let’s discuss the downsides.

  1. The split between source and headers, which makes project management quite slow. If you make all header libraries you’ll have a lot of copied code – the binaries will be larger. You’ll have to recompile that code every time you want to use it. And the split between the two is always troublesome – you can’t add a new field to your class without a few CTRL-TABs until you find where to write the proper definition.
  2. You still can’t write template code in .cpp files. You have to write code in the headers. If you mix that with some #ifdef & friends, it becomes a mess quite fast. Not to mention that you include content that is really implementation dependent.
  3. C++ still uses the C preprocessor. That is the first feature that should’ve gone from the language. If you think about it, the header should represent the features that your object offers and not a letter more. However, people ended up delivering these huge files that can be used everywhere even if they will be used in one place and one place alone.
  4. Namespaces are useless and make the code way too verbose. Instead of making your code cleaner and clearer, the programmers will end up doing a using namespace xxx. If you don’t believe me, look at how the code for using the duration_cast looks without some usings (auto only hides the dirt under the rug).
  5. Lack of ABI makes it impossible to deliver C++ components without a C interface. If you don’t, you’ll crash quite fast when you use the flag -fsuper-duper-new-feature because you should’ve used the flag -fsuper-duper-extra-cool-newer-feature.

5 are enough. There are others, but let’s move on.

It’s a barely portable language

Theoretically you write stuff in one place and you should be ready for… wait a minute. Did you really use <unistd.h>? And did you dare use the std::to_string call? You’re stupid, that doesn’t work under the C++14 compiler under Windows except for Microsoft’s. Why? Well, why not? We love to be arbitrary like that.

Portability is a hard thing in C++. You have to work for it, you have to make sure that you’re doing special stuff for it. C++ is amazing, don’t get me wrong, but in the past 15 years the only non-portable code I’ve seen was written in C++, or was caused by the interaction with a C++ native layer. C++ is mostly portable except when it’s not.

I think it’s easier to achieve true portability under C# or Java, because there’s an „all or nothing” feeling about them – either they have the whole core system ported, or they don’t work at all. That said, you still end up using C/C++ layers, and I love C++ for that, but remember, I offer a look at the bad part.

It’s a counterproductive language

I like to call myself stupid. It’s obvious that I am, that’s why I became a programmer – to make computers do the work for me, because I’m not to be trusted. That’s the case for my instant crush for C# – they have one simple model to refer resources – pointers, hidden by the lack of special notation – moron friendly, so it was a natural match.

I wanted to start a Breakout clone in C++. I had an array of widgets. Those widgets had textures. Those textures were copied over and over and over again, because containers can do that, so I had to go back to rethinking the storage class for the widgets.

I explained about the productivity hit I have when I have to search for a header file and add a few bits there, then go to the constructor (another file) to initialize it, then implement its usage in the header file (because templates) then go back in the other file to make sure another function makes proper use of it. If you put this in the context of IDEs unable to add a field to a class or rename a field of a class…

You can’t just take a DLL and use it as such. You need to have a „development package” which consists of pre-built binaries and huge header files that you need to compile with certain flags.

Should I go on? It’s kind of late for me, so I’ll just move on to the next chapter:

STL and Boost suck

They do suck and they suck big time. Please have a look at this wonderful code:

auto t1 = std::chrono::high_resolution_clock::now();
f();
auto t2 = std::chrono::high_resolution_clock::now();

// integral duration: requires duration_cast
auto int_ms = std::chrono::duration_cast(t2 - t1);

// fractional duration: no duration_cast needed
std::chrono::duration<double, std::milli> fp_ms = t2 - t1;

I can’t really write this from memory. And even if I could , I wouldn’t, it’s insanely long. I can write the code below without looking at the API, though:<br />

var t1 = DateTime.UtcNow();
f();
var t2 = DateTime.UtcNow();
var diff = t2 - t1; // that's a TimeSpan right there.
int int_ms = diff.TotalMilliseconds;
double fractionalMilliseconds = diff.TotalMilliseconds; // it's floating point by default.

Which one is more readable? I know that the C++ version can do some amazing tricks. I could write the C++ code from memory, but I refuse to keep this in mind. And that std::chrono is really killing me.

When you compare the amazing Linq extensions to the STL algorithms that are ugly to use and unreadable in the final code, you really wonder why should you even bother. Let’s compare.

// all_of example
#include <iostream>   // std::cout
#include <algorithm>  // std::all_of
#include <array>      // std::array

int main ()
{
  std::array<int,8> foo = {3,5,7,11,13,17,19,23};

  if ( std::all_of(foo.begin(), foo.end(), [](int i){return i%2;}) )
    std::cout << "All the elements are odd numbers.\n";

  return 0;
}

C# equivalent (and seriously written from memory)

using System.Linq;
using System;

namespace X
{
  class Program
  {
    static public Main (string[] p)
    {
      var arr = new int[] {3,5,7,11,13,17,19,23};
      if (!arr.Any(x => x%2 == 0))
      {
        Console.WriteLine ("All the elements are odd numbers.");
      }
    }
  }
}

Notice the „unreadable code” from C#, even the portability issue (hint: \n does not always do what you think it does). And there’s no reason why the C# version would be any slower than the C++ code, if you don’t mind the JIT work.

I’m comparing C++ with C# because it’s easy for me to write C#. And it would not be very hard for the C++ standard library to look as readable. STL has bad names for everything, especially that erase/remove thing which doesn’t do what you think it does. Then push_back and emplace_back, which is the sort of distinction that shows you’re not focusing on the task to solve, but on how the function that you use works. You’re spending time thinking about a very specific detail that you should really not care about. You should use the fastest (which is emplace_back, I think).

Then you have the std::shared_ptr or std::unique_ptr, which you should see a lot more often than the poor *. The code becomes incredibly hard to read when it has a lot of text with tags in them, like X_ptr code does. It really looks ugly, and things like these add-up, they make STL horrible to work with. And now Boost. Boost is a huge thing. Once you get to use a bit of boost you get to use a lot of it, it’s inescapable. And the APIs are quite bad, in tone with the STL badness. I’m sick of underscores in APIs, (underscore is hard to type), but that’s not why I dislike Boost. I’m sick of stupid naming of things, but that’s not why I dislike Boost. I dislike Boost because it’s too big and I cannot really follow their complex mindset. I still have problems accessing their simplest APIs, the documentation is, as always, amazing except when it isn’t, and so on. And the reason for the added complexity (and their almost autoerotic obsession for templates)? Well, it’s mostly header-files, therefore what you don’t use will be thrown away. Ah, perfect, but I still have to compile it every single time.

I will not cherry-pick the bad examples from boost because I really don’t want to search through the garbage bin to show you stuff that are messed up and degraded. What’s clear, however, is that boost libraries are a guarantee that your resulting code is as template heavy and as unreadable as possible. If not, that’s fine, there is a new release right around the corner. And I’ll leave you the freedom to tell me that I’m ignorant and I don’t know boost. I don’t, and, most importantly, I shouldn’t. These things shouldn’t be memorized.

C++ sucks

It does. There is a fun subset, it’s fun to have immense power, but as a language it can suck a lot. STL is ultra-verbose, namespaces are useless, you shouldn’t use features that are there to be used, and so on. The language is too complicated, it respects too much of the C legacy, and C can be a messy language. It doesn’t offer you the possibility to transmit a minimal set of binaries with self-describing metadata, we need to build huge kits for development. C++ is the immature old man of the programming world.

I still love C++, despite what redditors think, but it’s still ugly from many points of view.