56

We are trying to test some code under C++17 and its change to std::uncaught_exception. I can't seem to get GCC to provide the value of __cplusplus:

$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$

And:

$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.

What is the value of __cplusplus when using C++17?

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • 4
    Add the switch `-xc++` (it still ptobably won't be correct though) – Galik Jul 19 '16 at 10:41
  • 1
    I believe that the most recent standards drafts still have the old C++14 value, so there isn't an official one yet. – TartanLlama Jul 19 '16 at 10:45
  • 1
    If all you want is to test whether `std::uncaught_exceptions` is available, you should use the [feature testing macro](https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations#recs.cpp17) `__cpp_lib_uncaught_exceptions`. – cpplearner Jul 19 '16 at 11:01
  • Thanks Galik. GCC should be invoking cc1plus rather than cc1... Now open on the GCC bug tracker: [Issue 71930: g++ invokes the wrong preprocessor](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=71930). – jww Jul 19 '16 at 11:20
  • Thanks cpplearner. I'm guessing (and its only a guess) some compilers won't use `__cpp_lib_uncaught_exceptions`. Microsoft's VC++ and SunCC come to mind. I've found `__cplusplus` is a better test because it paints with a broad brush. I can then one-off the compilers that do their own thing, which is usually VC++. – jww Jul 19 '16 at 11:52
  • There is no C++17 yet. – Nicol Bolas Jul 19 '16 at 15:51
  • Thanks Nicol. We are trying to get ahead of the upcoming changes for C++17. Especially the ones that have the propensity to cause trouble for us. – jww Jul 19 '16 at 22:52
  • If everything gets wrapped up in the Toronto meeting, then perhaps it will be 201707. – chris Jul 22 '16 at 20:47

6 Answers6

71

tl;dr: For C++17, __cplusplus is 201703L.

What is the value of __cplusplus when using C++17?

According to the draft standard N4594 §16.8/p1 Predefined macro names [cpp.predefined] (Emphasis Mine):

The following macro names shall be defined by the implementation: __cplusplus The name __cplusplus is defined to the value 201402L when compiling a C++ translation unit.156

156) 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.

However the same value is appointed for the C++14 standard. Apparently it seems so, that there's no official/standard __cplusplus value set yet for the C++17 standard.

In GCC versions 6.1 and 7.0 the value is changed to 201500

Live Demo

In Clang version 3.8 and 3.9 the value is unchanged 201406.

Consequently, you'll have to wait a little bit for the standard value to come out.

--- Update ---

According to the C++ standard §19.8/p1 Predefined macro names [cpp.predefined] (Emphasis Mine):

1 The following macro names shall be defined by the implementation:

__cplusplus The integer literal 201703L.

Thus, the value of __cplusplus when using C++17 shall be 201703L.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
101010
  • 41,839
  • 11
  • 94
  • 168
  • 1
    Ah, I missed your update... I see `g++ -x c++ -std=c++14 -dM -E - – jww Feb 21 '18 at 22:56
  • I take it `__cplusplus` doesn't return the same value for Visual Studio 2017 when setting the language option specifically to c++17? I get `199711` returned when using the macro. – kayleeFrye_onDeck Jun 07 '18 at 22:10
  • 1
    Hm, okay, that's actually an open bug right now... https://developercommunity.visualstudio.com/content/problem/120156/-cplusplus-macro-still-defined-as-pre-c11-value.html – kayleeFrye_onDeck Jun 07 '18 at 22:11
18

I would try:

#if __cplusplus > 201402L
  // C++14 code here
  ...
#endif

In other words, testing for greater than C++14 should work as compilers add more features. As someone mentioned above, GCC uses 201500L. It looks like clang uses 201406L (four months after C++14 I guess).

Using the above snippet should be cross-platform and will work even when C++17 comes out with real value for __cplusplus. For more details about evolving features try the feature test macros.

Ajay
  • 18,086
  • 12
  • 59
  • 105
emsr
  • 15,539
  • 6
  • 49
  • 62
  • Personally, I think SD-6 should include __cpp_1998 __cpp_2011 macros that give you the exact month and year. – emsr Oct 05 '17 at 20:24
  • 1
    What is more correct? to say `#if __cplusplus >= 201703L` or `#if __cplusplus > 201402L`? – alfC Nov 12 '18 at 18:19
  • 1
    @alfC `#if __cplusplus > 201402L` would be true on c++1z, 17, currently 2a... and so on, but not c++14 or before that. In other words, this can be useful when using any old compiler before March 2017, given that you are using a ready-to-use feature of the c++17 that the old compiler already provides. When using recent compilers, I would prefer `>= 201703L` more. – sandthorn Dec 04 '18 at 04:24
  • 1
    The 201500L was used in a pre-c++17 version. So it would not clash with c++14 and was not a complete C++17 compiler either... (for example the `[[fallback]]` attributes would not work right even though it was semi-recognized.) – Alexis Wilke Jun 25 '19 at 06:09
14

Normally you should use __cplusplus define to detect c++17, but by default microsoft compiler does not define that macro properly, see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - you need to either modify project settings to include /Zc:__cplusplus switch, or you could use syntax like this:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
jhasse
  • 2,379
  • 1
  • 30
  • 40
TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
7

I realize you asked this question citing the Gnu C++ compiler as the one you're using, but you may want to have some awareness of what happens on the Visual C++ compiler, and strictly speaking, your question didn't ask about a specific compiler.

Currently, as of the date of this posting, the VC++ 2017 compiler sets __cplusplus to 199711L rather than what you might expect if you set the compiler to use c++17.

To get it to report correctly, you have to also set /Zc:__cplusplus.

(source: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 )

As to why? Well... in their words:

We tried updating the macro by default and discovered that a lot of code doesn’t compile correctly when we change the value of __cplusplus.

(source: https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/)

Joseph Van Riper
  • 512
  • 7
  • 17
3

I don't really know why __cplusplus doesn't show up as a regular macro, but I'm guessing it's so you can't redefine it. This is how I determine the its value.

#include <iostream>
int main( int argc, char** argv )
{
  std::cout << __cplusplus << std::endl;
  return 0;
}

Then compilation shows the value.

$ g++-6 test.cpp && ./a.out
201402
$ g++-6 -std=c++17 test.cpp && ./a.out
201500

I would check whether it's >= 201500 as opposed to checking for any specific value.

robert
  • 33,242
  • 8
  • 53
  • 74
1

A modern compile time check that you can put in any file that needs it:

static_assert(__cplusplus >= 201703L, "This file expects a C++17 compatible compiler.");
Cameron Tacklind
  • 5,764
  • 1
  • 36
  • 45