Feb 13, 2012

Even more rope to shoot yourself in the foot

The title of this book describes what I consider to be the main problem with both C++ and C: the languages give you so much flexibility that, unless you're willing and able to discipline yourself, you can end up with a large body of unmaintainable gobblygook masquerading as a computer program. You can do virtually anything with these languages, even when you don't want to.
Allen I. Holub

C++11 is already here. I'm not going to make another overview of all the good new things in it. Actually, I don't know much about those good new things. What I'm going to make - is an overview of why these good new things don't matter much (and why I am not too ashamed of not knowing much about them). There are few reasons.



First of all, you are not going to find a 100% standard-conforming C++ compiler. Even for a previous standard. If you open MSDN on almost any interesting C++ related topic, you'll see a "Microsoft Specific" section that could be larger than the rest of the page. Searching for unresolved issues containing "C++" in GCC Bugzilla finds 1055 issues at the time I write this words. Only Comeau is said to support everything, but who is using Comeau??

Most of my professional experience is from writing C++ code for a limited devices - game consoles. The story of C++ support on consoles is even more gloomy. If you open the documentation for CodeWarrior for DS, you'll see lots of information on what C++ features are implemented, and on non-standard C++ extensions. When we complained on official DS debugger having problems with understanding C++ code, we were answered, that C++ support in the debugger is experimental. I mean, it was not a question, what C++ standard it support, it was a question if C++ is supported at all!

So why there's so many C++ compilers, and no compliant one? The reason to it is that C++ language is too damn complicated. Come on, have you read all the 1300+ pages of the C++ standard? There's so many corner cases, that when you do write C++ code you are to keep it as simple as reasonable. This way you may hope that switching to another compiler would require rewriting just few pieces of your code (still having illusions of cross-platform compatibility??).

Another reason for keeping the code simple, is because otherwise you are risking to get a gunshot wound.

C makes it easy to shoot yourself in the foot; 
C++ makes it harder, but when you do it blows your whole leg off.
Bjarne Stroustrup

Everyone knows that debugging is twice as hard as writing a program in the first place.
So if you're as clever as you can be when you write it, how will you ever debug it?
Brian Kernighan

Writing code is about readability. The more complicated your code gets, the more time will be spent reading it. With C++ you have to restrict yourself from writing a too clever code even without C++11. "Enough Rope to Shoot Yourself in the Foot" was published in 1995. Think you are out of rope already and you need new standard? Now imagine for a second that you have to debug some code with move semantics involved. Do you feel happy?

Now, to summarize things, you will not be using C++11 features because they will not be supported by your compiler (just read "Why We Can’t Afford Export", it's written by Herb Sutter!! Or read this.). And when they become supported, you will not be using them because of compatibility and clarity reasons. That is why I think all that C++11 celebration and rapture are overrated. It's more like the standard authors are living in some other, better but imaginary world.

The C++11 Lands

3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. I can't agree with your opinion. First of all, I think it's worth for you to get more familiar with C++11 features even though you aren't going to use them at your job. I'm sure you will treat C++11 in more positive way after it.

    If I understand you right you say that C++11 could decrease the code's readability. Surely it could! But only if used in wrong way, so as the whole C++. Here are some examples that show how C++11 improves code readability and safety:
    1. map < string, int > m;
    // without C++11
    for (map < string, int >::iterator i = m.begin(); i != m.end(); ++i) {
    // do something with _i_
    }
    // with C++11
    for (auto i : m) {
    // do something with _i_
    }

    Not only the second for-loop is easier to understand, it is also safer.
    2. int a[1000];

    struct Compare {
    bool operator() (int x, int y) { return a[x] < a[y]; }
    };

    /* Lots of code */

    std::vector b;
    std::sort(b.begin(), b.end(), Compare()); // without C++
    std::sort(b.begin(), b.end(), [](int x, int y) {return a[x] < a[y];}); // with C++

    To my mind, the second type of std::sort call is more readable to my mind because you can see the comparator next to it.

    Now about compilers. Yes, it's sad that none of the compilers support the entire language. But the world isn't perfect :( And I think most programmers develop their projects on one C++ compiler. They could explore what C++11 features it supports and use them.
    "Now, to summarize things, you will not be using C++11 features because they will not be supported by your compiler. And when they become supported, you will not be using them because of compatibility and clarity reasons."
    I think it is the case only for long-running huge projects. I would use C++11 for a new project, I would use C++11 to increase code clarity (as in the upper examples), and compatibility can sometimes be achieved by refactoring.

    So C++11 is not so bad. Of course when used in a wrong way it is Another Rope to Shoot Yourself in the Foot :) But it can really increase the code's quality.

    ReplyDelete
    Replies
    1. Ilya, thank you for the comment. I generally agree with you that C++11 has a good side. After all, there would be no reason for it otherwise. What I'm pointing at is that there's a bad side as well, and this bad side is significant.

      I agree that foreach loops and anonymous functions are good things in principle. E.g. in C# they are an organic part of the language. But for C++ it could be another story.

      The C++ language is already damn too huge. I don't think that somebody (well, maybe except for Bjarne Stroustrup and Andrei Alexandrescu) may frankly claim to know if fully in all details. This is one of the reasons for that shooting own limbs with it is so simple.

      It is full of different concepts. And because of the compatibility reasons it is not possible now to remove parts that are now considered not ideal. Now adding more to the language conceptual weight seems to be not a really great idea..

      For example have a look at the lambda function declaration. Starting it with '[]' symbol may seem pretty ugly, and certainly has nothing to do with the common usage of square brackets - indexing. It was chosen just because this symbol combination was illegal in previous C++ versions, so it would not break the legacy code. So it's more like a hack, a forced solution, rather than a good design choice.


      Now here are the parts of your comment that I cannot agree with.

      "Yes, it's sad that none of the compilers support the entire language. But the world isn't perfect :("

      I believe this is not the world's but the language's flaw.


      "And I think most programmers develop their projects on one C++ compiler. They could explore what C++11 features it supports and use them."

      This one I cannot agree with. Normally the C++ libraries are developed to support most of the widespread compilers. And if you look into code, you'll find lot's of #ifdef's dedicated to work around or wrap compiler-specific issues.

      Even if you are not writing a super-duper cross-platform code, you'll probably want to have a possibility to switch to another compiler. And surely you'll want other programmers to be able to read and understand your code. So you'll be sticking yourself to not use compiler-specific features..


      "I would use C++11 for a new project, I would use C++11 to increase code clarity (as in the upper examples)"

      But why would you use C++ for a new project, in a first place? If you are free to choose other languages, it will probably be more reasonable to do so.

      But if you are forces to use C++, you'll probably have not much freedom with the code as well, as I described above. For cross-platform library code, you'll want to be as conservative as possible. For limited platforms you'll probably be constrained by an fossil compiler. For GPGPU applications (that's what you do, right?) you have to use a subset of the language.. What other reasons do you have to choose C++?


      As a conclusion, I think that C++ became so huge and overengineered, that it might worth to split it into a number of sub-languages. While it sounds like a joke, it still might be reasonable.

      Delete