11

I want to use some C++11 features in my program. I might have to share my source code with others in future. How do I assert, inside the code, that C++11 should be used to compile my program? An older compiler might throw an error, but I want the user to be informed clearly that C++11 is required.

I'm using the following C++11 features, if that matters:

  • enum with storage size specified
  • std shared pointer

thanks

Neha Karanjkar
  • 3,390
  • 2
  • 29
  • 48
  • 4
    `static_assert(true);`. (I'm joking. Don't do this.) – jamesdlin Apr 14 '13 at 10:12
  • Be aware that at time of writing, there is no compiler that fully supports C++11. So if you test for complete C++11 support, you'll have a lot of false negatives -- compilers that have the features you need but which don't implement C++11 and so are rejected by your test. – Steve Jessop Apr 14 '13 at 12:26
  • @SteveJessop I had the impression that GCC already supports all of the C++11 features according to [this table](http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport). If I'm wrong, please, correct me. – Malcolm Apr 14 '13 at 17:01
  • @Malcolm They support the majority of them, but some details can be perfected and the libstdc++ is not not fully C++11-compliant. – Morwenn Apr 14 '13 at 21:20
  • @Malcolm: http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x. Lots of progress, but still some significant omissions. – Steve Jessop Apr 16 '13 at 10:37
  • Time to explore `cmake`. – Dilawar Dec 21 '17 at 06:18
  • @Dilawar Moved to Scons years ago. For a comparison between cmake, Scons and other such tools: https://github.com/SCons/scons/wiki/SconsVsOtherBuildTools – Neha Karanjkar Oct 01 '18 at 04:22

3 Answers3

22

You could check that the value of the __cplusplus macro is 201103L or greater:

#if __cplusplus < 201103L
#error This code requires C++11
#endif

C++11 16.8 Predefined macro names:

The following macro names shall be defined by the implementation:

__cplusplus

The name __cplusplus is defined to the value 201103L when compiling a C++ translation unit. (155)

(155) It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming compilers should use a value with at most five decimal digits.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Should I use something like #if _cplusplus == 201103L {my code} #elif {display error} ? – Neha Karanjkar Apr 14 '13 at 10:15
  • @NehaKaranjkar: Don't compare for the equality. I've updated the answer with an example. – NPE Apr 14 '13 at 10:16
  • I just learned about the #error directive. Thanks. +1 to both answers mentioning this. – Neha Karanjkar Apr 14 '13 at 10:22
  • `__cplusplus` is broken on Windows, see http://stackoverflow.com/questions/14131454/visual-studio-2012-cplusplus-and-c-11 –  Apr 14 '13 at 11:06
  • @IngeHenriksen Agreed. Since VS 2012 doesn't even support C++98 (much less C++11), the value should be a 5 digit number. (Supporting one or two odd features from C++11 doesn't mean that you support C++11.) – James Kanze Apr 14 '13 at 11:12
  • 1
    Likewise, all those C++98 compilers that didn't support `export` shouldn't have set it to `199711L`, although some did. There's a practical problem with the value of the `__cplusplus` macro, which is that it's not designed to help tell the difference between a compiler that doesn't conform to C++98, and a compiler that doesn't conform to C++11 ;-) – Steve Jessop Apr 14 '13 at 12:12
  • I'm using gcc 4.6.3 with the -std=C++0x flag, and the check for __cplusplus < 201103L fails. So does the check for 199711L. Am I doing something wrong? – Neha Karanjkar Apr 15 '13 at 07:07
  • @Neha See my answer below: before GCC 4.7, `__cplusplus` is set to 1 for `-std=c++0x`. That's why you should consider using `Boost.Config` for the check. – Morwenn Apr 15 '13 at 08:30
9

__cplusplus macro may come handy

#if __cplusplus < 201103L
#error C++11 Required
#endif

Something like this

alexrider
  • 4,449
  • 1
  • 17
  • 27
  • 2
    The example structure works, but I'd go for checking less than the C++11 value. – chris Apr 14 '13 at 10:12
  • @rhalbersma: I agree with the technicality of your observation though I really don't think another ratification is happening any time soon. C++03 ---> C++11, 8 years ha.. – Alok Save Apr 14 '13 at 10:16
  • It will have greater date and expected to be backward compatible with c++11 – alexrider Apr 14 '13 at 10:16
  • 1
    @AlokSave, Last I heard, C++14 was well on its way. A year or so ago, people decided they would get cracking on moving C++ forward faster. – chris Apr 14 '13 at 10:17
  • @chris yes Bjarne Stroustrup seemed to have outdated FAQ. – alexrider Apr 14 '13 at 10:19
  • @chris: How long did we hear similar rumors about C++11, i really doubt those. – Alok Save Apr 14 '13 at 10:20
  • @alexrider, It was written before C++11 came out. You can easily tell be the fact that he says it *will* be set. – chris Apr 14 '13 at 10:20
  • @AlokSave, You must have seen http://isocpp.org/ by now. Fact is that concepts were actually delayed until C++17 because there wasn't enough time to get it all ready in time for C++14. Instead, they're trying to at least get the constraints part in. – chris Apr 14 '13 at 10:22
  • @AlokSave 100+ papers for the upcoming Bristol committee meeting. the pace of development is very high, but of course standardization might be considerably smaller in scope – TemplateRex Apr 14 '13 at 10:24
  • @rhalbersma: if you're concerned about future backward-incompatibilities then you can test for exact equality. And that is a valid concern, for example in N3424 Herb Sutter calls for a breaking change in respect of lambdas ASAP. In fact, implementations of any future versions of the standard are pretty well *guaranteed* not to conform to the C++11 standard. Even if no syntax or semantics are changed, they will have a different value of `__cplusplus` and thus not conform to C++11. So it is not intended that any major release of the standard is truly compatible, although corrigenda might be. – Steve Jessop Apr 14 '13 at 12:18
5

As it has already been said, the correct solution would be to check for the __cplusplus macro. However, some compilers have a partial support for C++11 features but do not set this macro for the correct value. For example, strongly-typed enumerations are available in g++ since GCC 4.4.0. However, with the option -std=c++11 (and its equivalents), the macro __cplusplus was not set to the good value before GCC 4.7.0 (it was set to 1 instead). That means that some compilers can compile your code but won't if you check for C++11 that way.

If you just need specific features, then I would check for them with Boost.Config which defines a whole set of macros that can be used to check whther your compiler supports the required features. In your case, you would need:

  • BOOST_NO_CXX11_SCOPED_ENUMS for strongly-typed enumerations.
  • BOOST_NO_CXX11_SMART_PTR for std::shared_ptr.
orlp
  • 112,504
  • 36
  • 218
  • 315
Morwenn
  • 21,684
  • 12
  • 93
  • 152