16 April, 2016

C++ Moving Forward

Time to move forward and require C++11 by default?

Although I don't use much of C++11 I'm becoming tired of making my code backwards compatible by using macros and other tricks. Removing all of this won't probably make much difference for me as I don't really like stl library. However, certain features like noexcept, move semantics, and constexpr are nice additions that I really like and every time I have to write a macro instead of the keyword I feel like working on a project, which is 20 years old.

ApiBegin

I already use many C++11 keywords and just define them if they are not available. I kind of developed my way of solving this problem without affecting other libraries and user code that is included after. I call it briefly as ApiBegin & ApiEnd. For example the following is from Blend2D's b2d_api_begin.h:

#if !B2D_CC_HAS_ALIGNAS && !defined(alignas)
# define alignas(x) B2D_ALIGNAS(x)
# define B2D_UNDEF_ALIGNAS
#endif // !B2D_CC_HAS_ALIGNAS && !alignas

#if !B2D_CC_HAS_NOEXCEPT && !defined(noexcept)
# define noexcept B2D_NOEXCEPT
# define B2D_UNDEF_NOEXCEPT
#endif // !B2D_CC_HAS_NOEXCEPT && !noexcept

#if !B2D_CC_HAS_NULLPTR && !defined(nullptr)
# define nullptr NULL
# define B2D_UNDEF_NULLPTR
#endif // !B2D_CC_HAS_NULLPTR && !nullptr

And also b2d_api_end.h, which clears such definitions to make no harm to people including Blend2D:

#if defined(B2D_UNDEF_ALIGNAS)
# undef alignas
# undef B2D_UNDEF_ALIGNAS
#endif // B2D_UNDEF_ALIGNAS

#if defined(B2D_UNDEF_NOEXCEPT)
# undef noexcept
# undef B2D_UNDEF_NOEXCEPT
#endif // B2D_UNDEF_NOEXCEPT

#if defined(B2D_UNDEF_NULLPTR)
# undef nullptr
# undef B2D_UNDEF_NULLPTR
#endif // B2D_UNDEF_NULLPTR

The intention is clear - this small hack makes Blend2D compilable by pre-c++11 compilers and allows Blend2D code itself to look more modern. I just use these features without making them ugly, for example noexcept looks much nicer than B2D_NOEXCEPT, etc. However, this also requires a really good compiler detection. Instead of solving this per-project I just wrote a tool to generate most of it. It's a monster, I know, but offers a centralized way of solving the compiler problem, and when a new compiler is released or some feature is wrongly detected a single fix fixes 'em all.

I don't even see a problem in my approach. It's clean, it makes the project backwards compatible, and it allows me to use at least some features I found useful. However, the problem that I see is that many projects just switched to C++11 and don't look back. So I'm asking myself, is it time to switch now or it's better to wait? It's not that long time ago I was asked to make asmjit compilable by VS2003 (yeah), and it was possible (maybe it still is, I don't know). But these seem to be rare cases to base any decision on them.

ApiEnd

Okay, this was a short boring post :) Next time I should finally write something about Blend2D, but I don't yet have a clue where to start. Maybe I can reveal that I finally bought an AVX2 capable machine so Blend2D will be released with a fully optimized AVX2 pipeline codegen?

3 comments:

  1. Recent GCC versions switched to C++14 by default (https://gcc.gnu.org/gcc-6/changes.html), while clang still defaults to gnu++98 (https://github.com/llvm-mirror/clang/blob/fa0c754/lib/Frontend/CompilerInvocation.cpp#L1512)

    ReplyDelete
  2. Is there any significant C++ compiler out there that does not support the C++11 constructs you're using?

    I'm all in favor or not trying to support older compilers when new ones are so easily usable (plus, you know, the C++ community is quite good at keeping up to date :) the VC++6 era is now forgotten :))

    ReplyDelete
  3. I've given up on anything pre-C++11 myself -- heck I'm rapidly heading towards moving the goalposts to C++14 for saner constexpr behavior. The only thing holding me back on the latter is MSVC's awful support for C++14 features.

    ReplyDelete