writing code that supports new and older c++ compilers? - c++

I have to write a code that can support newer and older compilers and i was wondering before i start is something like this possible?
#ifndef C++11 { //some code..... }
#endif
else
#ifndef older C++ version { //some code......}
#endif

The standard requires C++11 conforming implementations to define a macro named __cplusplus to the value 201103L. Nonconforming compilers are recommended to use a value with at most five decimal digits. The same was true for C++03 where the value this should be defined to is 199711L.
However, not many compilers consider(ed) themselves standards compliant, and e.g. gcc defined this for a long time to be just 1L. Also you have to consider that it is not only the compiler version, but also the parameters to the compiler. Gcc only supports (part of) C++11 when you pass -std=c++0x or -std=gnu++0x. In these cases it will define a macro __GXX_EXPERIMENTAL_CXX0X__.
So the most portable solution is to be unportable and have your own macro that you set when C++11 support is detected, and have some header/configure script in which you use the aforementioned things, along with possibly others for other supported compilers.

There's no simple universal macro, and for most compilers, it's not a binary "yes or no". Most compilers implement some C++11 features, but certainly not all.
MSVC simply has a single _MSC_VER macro indicating the version of the compiler, and if you know which features are supported by which version, then you can use that.
Clang has pretty comprehensive feature-specific macros, of the form _HAS_<feature> (I can't remember if that's the precise name).
If you want to know, across all compilers, whether feature X is available, you'll have to check all these different macros and determine the answer yourself. :)

In MSVS you have the macro, _MSC_VER which can help you. I don't know if there's such a standard macro.

The C++ standards committee spent a lot of effort to make sure, that any code written to the older standard is still valid in the new standard. And if you have to do without a feature on some platforms, using it on the others is a lot of work for rarely any gain. So just stick to the older version you need to support.
For the few exceptions the most reliable way is to test the compiler and define macros to choose the version you want to use. Either manually if you know your set of compilers or using something like autoconf or cmake if you don't. There are many compilers that support some C++11 features and not others, so there's little hope to find some test that would suffice without any work on your part. I believe all the features can be tested with just compiling; if they compile, they will generally also work.

Write your code to be compliant with the most recent compiler.
Any code which won't compile against an older version should be extracted into its own .cpp unit.
Then an alternative .cpp should be written for the old compiler.
For older builds select to include the older .cpp.
You don't need #defines.
See #ifdef Considered Harmful

Related

Can't set c++ version in CMake [duplicate]

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?
This has already been submitted to Microsoft for review:
A value of predefined macro __cplusplus is still 199711L
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.
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.
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.
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.

Why does my VS 2015 still use the C++98 compiler version? [duplicate]

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?
This has already been submitted to Microsoft for review:
A value of predefined macro __cplusplus is still 199711L
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.
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.
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.
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.

Recognize non-standard C++ portably?

C has __STDC__ but there seems to be no standard way of recognizing some extended C++ dialect. Hence for portable code I use
#define __is_extended \
((__GNUG__ &&!__STRICT_ANSI__) || \
(_MSC_VER && _MSC_EXTENSIONS && __cplusplus) || \
(__IBMCPP__ && __EXTENDED__))
This works for gcc, XLC and Visual C++ so far.
We have to test ISO/ANSI conformity idiosyncratically per compiler, right? If so, can you make suggestions for other compilers that have proven to work?
EDIT: Since there was so much discussion about the for and against of such tests, here's a real world example. Say there is some header stuff.h used widely with multiple compilers in multiple projects. stuff.h uses some compiler-specific vsnprintf (not standardized before C++11), some copy_if<> (they somehow missed it in C++98), own mutex guards and what not else. While implementing a clean C++11 variant you wrap the old (but trusted) implementation in some #if __is_extended (better: __is_idosyncratic or !__is_ANSI_C11). The new C++11 goes behind an #else. When a translation unit that still compiles as C++0x or C++98 includes stuff.h nothing changed. No compilation errors, no different behaviors at runtime. The C++11 remains experimental. The code can be safely committed to the main branch, co-workers can study it, learn from it and apply techniques with their components.
Your question is actually backward, because the non-standard extensions supported by a compiler are specific to that compiler - often to the extent of being specific to a particular compiler version - as are the non-standard macros each compiler defines so they can be detected.
The usual technique is the reverse: specify some feature you want, associate it with some macro, and only write code which uses that feature if the associated macro is defined.
Let's say there is some funky feature that is supported - in exactly the same way by Visual C++ 11 and g++ version 3.2.1, but not with any other compilers (not even other versions of Visual C++ or g++).
// in some header that detects if the compiler supports all sorts of features
#if ((defined(__GNUG__) && __GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 1) || (defined(_MSC_VER) && _MSC_VER == 1700))
#define FUNKY_FEATURE
#endif
// and, in subsequent user code ....
#ifdef FUNKY_FEATURE
// code which uses that funky feature
#endif
There are plenty of freely available general purpose libraries which use this sort of technique (obviously with better naming of macros). One example that comes to mind is the ACE (Adaptive Communication Environment) framework which has a set of portability macros, documented here.
Using such macros is not a job for the faint-hearted if you are concerned about a large set of non-standard features, given that it is necessary to understand what versions of what compilers (or libraries) support each feature, and to update the macros every time a new compiler, a new library, or even a patch is released.
It is also necessary to avoid using reserved identifiers in naming those macros, and to ensure the macro names are unique. Identifiers starting with a double underscore are reserved.
In general this will be hard to do because if you're relying on a non-conformant compiler then there's no standardized way to require only standard rules (the behavior of a non-standard compiler is not specified by the standard).
What you could do is adding an extra build step or commit hook and pass the code ALSO through a specific portable compiler (like g++) with specific strict conformancy options.
First, you are not allowed to name variables in such way (#define __is_extended) because names beginning with two underscores are reserved for the implementation.
The method you have is still compiler-dependent and could fail: apart from __cplusplus, none of those macros are standard and therefore the implementation is not required to define them. Moreover, that test is basically checking what compiler is being used not whether or not some extensions are being used.
My advice is simply not to use extensions. There's very very little need for them. If you still want to make sure they don't get used anyway, you may turn your compiler's flags to restrict the usage of extensions; for GCC, there's a whole chapter about this in the section "Options Controlling C Dialect".

What macro does Clang define to announce C++11 mode, if any?

What macro does Clang define to announce C++11 mode, if any?
GCC defines __GXX_EXPERIMENTAL_CXX0X__, at least some versions do. MSVC seems to have the support turned on by default at least for _MSC_VER >= 1600.
It uses different preprocessor tests for each separate feature, like
#if __has_feature(cxx_decltype)
for testing if decltype is implemented.
See the complete list here
http://clang.llvm.org/docs/LanguageExtensions.html#checking_upcoming_features
The standard says you can look at the value of _cplusplus to determine which standard the compiler is targeting. Although, in practice you may not be able to do much with this information. See Bo Persson's answer for a much better solution.
C++98/03 - 199711L
C++11 - 201103L
Clang defines the same macro, mostly for compatibility with GCC's libstdc++.
I seem to remember the devs liking feature-specific checks like in libc++ better:
(Scroll down some)

Checking for availability of C++0x algorithm additions

I'm trying to figure out which of the additions to the algorithm headers are supported by a given implementation (gcc and MSVC would be enough).
The simple way would be to do it the same way as one would do it for core features: check the compiler version and define a macro if a language feature is supported. Unfortunately I cannot find a list that shows the version numbers for either compiler.
Is simply checking for a generic C++0x macro (GXX_EXPERIMENTAL or __cplusplus) enough or should I check the change lists for the compilers and build my macros based on those lists?
http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x
Since all compiler vendors provide a nice list of what's available in what version, and you would test the functionality anyways, I would use compiler versions to check for specific features. Or demand the user uses at least a good version, and not worry about it.
__cplusplus is not necessarily a C++0x macro, it tells you nothing. GXX_EXPERIMENTAL has existed since GCC 4.3, so that's pretty useless too.
This one is for GCC.
This one is for MSVC. (mind you: partially implemented means broken)
This one is for Intel.
Here you can find what macros to check against for a specific version of a compiler.
As far as I could figure out the only proper solution is to have a build script that tries to compile and run a file that uses the feature and has a runtime assertion. Depending on the outcome have a #define CONFIG_NO_FEATURENAME or similiar in a config file and guard your uses and workaround with a #ifndef.
This way it is possible to check if
the feature is available
the feature functions properly (depending on the correctness of the assertion)