22

Anyone know why __cplusplus is defined as 199711L (which is the "old" C++) in my Visual Studio 2012 c++ project? Should it not say 201103L since VS 2012 now has C++ 11 support? Even if I include C++ 11 headers it still is wrongly defined. Any clues?

5 Answers5

16

This has already been submitted to Microsoft for review:

A value of predefined macro __cplusplus is still 199711L

273K
  • 29,503
  • 10
  • 41
  • 64
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks. I have added my own comment to the bug report. –  Jan 03 '13 at 00:49
  • 1
    We have 2014 now, VS 2013 is out and it seems that the flag still reports the old version (follow the discussion in above´s link). If you look here on the supported features, they even start pulling in C++ 14: http://msdn.microsoft.com/en-us/library/hh567368.aspx - " Visual C++ in Visual Studio 2013 expands this coverage even further, and also supports some select C++14 Library features." This I really don´t understand, why everybody can choose which features to implement. This will ruin portability more and more! – flohack May 12 '14 at 09:43
  • 1
    @flohack - If you watch the appropriate tech talks, you'll find out that the workload on the VS team to implement different features is... welll... different. Some things are fast, others are not. They do some fast things like add `make_unique` to the library, because it takes no time. You'd also learn that MS is pioneering several things for standardization, such as an async/await proposal, and so they prioritize that as well so that we have a working implementation with which to refine our ideas/proposals. It's not that they're choosing what to implement, it's that they're choosing when. – Mark Nov 23 '14 at 23:42
  • 1
    Mark, I agree. Then however, I question the pacing of the standards organization. If major vendors fall behind with implementing features, and then maybe the next iteration of the standard is already at the gates, it does not look as if it was a useful strategy for standardization, but rather a market hype instrument. As I learned in school, standards should help the industry (and the market) to make things more comparable, and to prevent unfair compatibility issues between vendors. And yet this is the case, the code portability can be seriously affected by this. – flohack Nov 25 '14 at 07:41
9

It really depends on what you expect that macro to actually mean. Should 201103L mean "This compiler fully supports all of C++11 in both the compiler and the library?" Should it mean "This compiler supports some reasonable subset of C++11?" Should it mean "This compiler supports at least one C++11 feature in some way, shape, or form?"

It's really up to each implementation to decide when to bump the version number. Visual Studio is different from Clang and GCC, as it has no separate C++03 compilation mode; it provides a specific set of features, and that's what it provides.

In general, a single macro is not a useful tool to decide when to use some feature. Boost.Config is a far more reliable mechanism. The standards committee is investigating ways of dealing with this problem in future versions of the standard.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
5

I am with Nicol on this one. The only reason to test for __cplusplus >= 201103L is to check whether you can use the new features. If a compiler implements only half of the new features but uses the new value of __cplusplus, it will fail to compile a lot of valid C++11 code protected by __cplusplus >= 201103L (I have some that uses thread_local and *this references). If on the other hand it keeps 199711L, it will use the safe C++98 code, which is still fine. It may miss a few optimizations that way, but you can still use other ways to detect if a specific feature is available (compiler version, compiler specific macros like __GXX_EXPERIMENTAL_CXX0X__, boost macros that check compiler macros for you, etc). What matters is a safe default.

There are 2 possible reasons to switch to the new value of __cplusplus:

  • your compiler has full support for C++11 (or close enough, there will always be bugs)
  • this is an experimental mode of your compiler that shouldn't be used in production, and what would normally be missing features count as bugs.

As far as I know, all compilers that have switched are in the second category.

I believe some compiler vendors have been way too enthusiastic about changing the value of __cplusplus (easiest C++11 feature to implement, good publicity), and it is good that some are more conservative.

Marc Glisse
  • 7,550
  • 2
  • 30
  • 53
4

As of April 2018 MSVC 2017 now correctlys reports the macro, but only if a specific switch is used (/Zc:__cplusplus). This is because a lot of old code relies on detecting the old value of the macro for MSVC compilers. Source

Hopefully in future, once people worldwide have updated their code, MS will report the macro correctly by default.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
metamorphosis
  • 1,972
  • 16
  • 25
  • Applies to Visual Studio 2019 as well (you need to manually add `/Zc:__cplusplus` to the project command-line options). If you rely on `__cplusplus`, add the command-line switch. And if you're using Visual Studio on Windows only, the `_MSVC_LANG` macro may be more suitable as this changes based on the selected C++ standard. Since there is a workaround, seems unlikely Microsoft will budge on this. – AlainD Feb 10 '21 at 16:05
2

As pointed out in another answer, /Zc:__cplusplus is pretty much the answer. Suppose you have a bunch of .vcxproj files underneath a folder hierarchy, simply place a file named Directory.Build.props into the common parent folder and populate it as follows:

<?xml version="1.0" encoding="utf-8"?>
<Project>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>

You could also use your very own user property sheets to set this there. I.e. in %LOCALAPPDATA%\Local\Microsoft\MSBuild\v4.0 inside all of the Microsoft.Cpp.*.user.props files (where * is the placeholder for the target platforms).

Furthermore it is probably sensible to be defensive about this in code, which means resorting to checking for both _MSVC_LANG and __cplusplus like so (or similar):

#if defined(__cplusplus) && defined(_MSVC_LANG) && (__cplusplus == 199711L)
// Check against _MSVC_LANG with the value you expect for __cplusplus
#else
// Check against __cplusplus as usual
#endif

I would recommend using something like this whenever you can't be certain that your code (e.g. a header, because you are a library author) is used while /Zc:__cplusplus was specified on the command line.

I'm still a bit puzzled why this is still the case as of VS2022, because if you look at C++ compiler support, Visual C++ isn't half bad compared to all the others.

All the above said, you may want to use feature test macros instead of testing for the C++ standard version.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152