Hello everybody.

In this post, a quick check: with what compilers does our current C++11 branch work?

The baseline is, of course, that the compiler should be from 2011, or more probably a bit later: those of you that were around at that time will remember that compilers didn’t catch up as fast as they do now (yes, kids these days have it easy). Thanks to the magic of Docker, I didn’t have to retrieve and compile old versions of gcc and clang, either: between the official images of Ubuntu Trusty (a distribution from 2014), Debian Jessie (initially from 2015, but kind of conservative) and Centos 7.0 (also 2014, and also updated cautiously) I could throw together a decent set of compiler versions. Microsoft makes older versions of Visual C++ available, too.

As I suspected, compilers from 2011 and 2012 were not yet up to the task. gcc 4.6.3 didn’t support static data-member initialization, the override keyword, or defaulted destructors (and for good measure, its C++11 mode was still called -std=c++0x); clang 3.0 did better, but couldn’t use initializer lists to return values; and Visual C++ 2012 choked on most of the above and the noexcept keyword.

After a couple of years, though, the picture got better. Both gcc 4.8 and clang 3.3, from 2013, could compile the branch successfully, and so can all later versions—with a couple of caveats. One is that, by changing compiler and thus library version, sometimes I’d find that our code was relying on a standard header that was included only indirectly. (I’m sure you’re a better person; I confess that, when the code compiles, I don’t always check that it includes headers for every feature it uses.) The other is that, even though the compilers had caught up, Boost sometimes didn’t; in particular, I had errors with the version of Boost included with older distribution because boost::hash_map was not specialized for std::shared_ptr. Switching to a more recent version of Boost cured the problem. As for Visual Studio, the 2015 version was successful; the 2013 version, however, joined gcc 4.7 in the “almost, but not quite” category (I suspect that clang 3.1 or 3.2 might belong there, too, but I didn’t find a distribution carrying those versions).

gcc 4.7.2 (released in September 2012) failed with a curious error which I didn’t stop to investigate. Here it is, reduced to a few lines of code:

    class B {
      public:
        virtual ~B() = default;
    };
    class D : public B {
      public:
        virtual ~D() override = default;
    };

The above fails to compile with:

test.cpp:9:13: error: looser throw specifier for 'virtual D::~D()'
test.cpp:4:13: error:   overriding 'virtual B::~B() noexcept (true)'

upon seeing which, I promptly closed the terminal window and walked away.

Visual C++ 2013 choked on all uses of std::bind (spewing multi-line errors about the expression losing const-volatile qualifiers when called), but I’m not overly worried about that; in the following of this experiment, I’ve been meaning to replace them all with lambdas anyway. What worried me more was that it also didn’t support the noexcept keyword, which is be nice to have since it has beneficial effects on performance. If we want to keep the noexcept specifiers (which I’d like) and if we want to support VC++ 2013 (which I’d also like, since it’s not so old as compilers used in finance go) we might need to hide the keyword behind a QL_NOEXCEPT macro that can be conditionally defined as either noexcept or nothing.

We’ll see, I guess—but the first step would be to remove those pesky bind calls. I’ll tell you about this another time, though.

So far, I didn’t find the time (or, indeed, the motivation) to research, install and moderate a comment system. If you want to reach out with suggestions or questions, please send me a tweet or an email. I’ll report on your feedback in future posts.

Follow me on Twitter if you want to be notified of new posts, or add me to your Google+ circles, or subscribe via RSS or email: the buttons for that are in the footer. Also, make sure to check my Training page.