Is there a way to detect at compile-time if the compiler supports certai开发者_如何学Gon features of C++11? For example, something like this:
#ifndef VARIADIC_TEMPLATES_SUPPORTED
#error "Your compiler doesn't support variadic templates. :("
#else
template <typename... DatatypeList>
class Tuple
{
// ...
}
#endif
There is a constant named __cplusplus
that C++ compilers should set to the version of the C++ standard supported see this
#if __cplusplus <= 199711L
#error This library needs at least a C++11 compliant compiler
#endif
It is set to 199711L in Visual Studio 2010 SP1, but I do not know if vendors will be so bold to increase it already if they just have (partial) compiler-level support versus a standard C++ library with all the C++11 changes.
So Boost's defines mentioned in another answer remain the only sane way to figure out if there is, for example, support for C++11 threads and other specific parts of the standard.
As stated by the C++11 standard (§iso.16.8):
The name __cplusplus is defined to the value 201103L when compiling a C++ translation unit.
With the value of that macro, you can check whether the compiler is C++11 compliant.
Now, if you are looking for a standard way to check if the compiler supports a whatsoever subset of C++11 features, I think there is no standard, portable way; you can check compilers documentation or std library header files to get more information.
I know that this is a very old question, but this question might be often seen, and the answers are a bit out of date.
Newer compilers with the C++14 standard have a standard way to check features, including C++11 features. A comprehensive page is at https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
In summary, each feature has a standard macro defined that you can check with #ifdef
. For example, to check for user defined literals, you can use
#ifdef __cpp_user_defined_literals
You can use this:
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
cout << "C++11 is supported";
#else
cout << "C++11 is not supported";
#endif
For C++11, most compilers set the __cplusplus
macro at 201103L
. But Visual Studio, depending on how old it is and how it's configured, sets it at 199711L
, which is the value used by other compilers for before C++11.
This code compares the _cplusplus
macro with 201103L
for all compilers except Visual Studio, and if the compiler is Visual Studio, it checks if the version of Visual Studio is later than 2015, the first version of Visual Studio which completely supports C++11 (for Visual Studio 2015, the _MSC_VER
macro has the value 1900
, see this answer).
For check support C++14 and other. Testing on GCC 5.2.1.
#include <iostream>
int main(){
#if __cplusplus==201402L
std::cout << "C++14" << std::endl;
#elif __cplusplus==201103L
std::cout << "C++11" << std::endl;
#else
std::cout << "C++" << std::endl;
#endif
return 0;
}
If you do not want to use Boost.Config and need to test for compilers that support C++11 then checking the value of the constant __cplusplus
will do. However, a compiler might support most of the popular features of the C++11 standard yet it does not support the entire specifications. If you want to enable support for specific Visual Studio compilers which are not yet 100% compliant to C++11 specifications then use the following code snippet which allows compiling in Visual Studio 2013:
#if defined(_MSC_VER)
# if _MSC_VER < 1800
# error This project needs atleast Visual Studio 2013
# endif
#elif __cplusplus <= 199711L
# error This project can only be compiled with a compiler that supports C++11
#endif
A complete list of versions of the compiler for Visual Studio is provided at How to Detect if I'm Compiling Code With Visual Studio 2008
In the traditional Linux/Unix world, autoconf is traditionally used to test for the presence of libraries and compiler features and bugs placing them into a config.h that you use in your files as needed.
Quick history
When this question was asked in February 2011, support for C++11 was inconsistent. Compilers needed time to catch up to the standard, so in the meantime, they released with partial support. For example, a compiler might have implemented variadic templates, but not auto
.
If you had code that depended on a subset of C++11 features, you didn't have a standard way of asking the compiler whether it supported them specifically.
You could check for overall C++11 support with #if __cplusplus >= 201103L
, but:
- That constant and its meaning weren't technically official until the standard was accepted later, in August 2011.
- This was too coarse. Compilers probably only set
__cplusplus
to201103L
once they had full feature support—and no one had full feature support yet. So, if you used this, you would unnecessarily reject most or all of the compilers that people would want to use to compile your code.
One pragmatic solution was to use the third-party Boost.Config library, which maintained a bunch of feature test macros. Boost.Config
's maintainers kept track of which compilers supported which features, and updated the macros accordingly for each Boost.Config
release.
(This stuff about Boost is based on an early, now-deleted answer from @James McNellis.
Today
C++11
Today, there's a version of every major compiler that supports the whole C++11 standard. .
If your code requires any of C++11, it's now reasonable to require that the compiler supports all of C++11. So, use #if __cplusplus >= 201103L
. (See @Paulo M's answer for a standards reference for this macro.) But beware that there are complications with MSVC—see @Donald Duck's answer.
Beyond
Since C++20, in addition to the coarse-grained __cplusplus
macro, you can also #include <version>
to get a bunch of feature test macros. This is basically a standards-based alternative to Boost.Config
.
According to this answer from Jarryd, these macros are actually available in at least some 2016-era C++14 compilers.
When your check is for a C++11 library availability (not a language feature), for example the <array>
header, you can #if __has_include(<array>)
.
Sometimes checking #if __cplusplus >= 201103L
would tell you that you use C++11 but other settings like the standard library version setting in Xcode may still not have the new libraries available (most of them are available in different names ie <tr1/array>
)
精彩评论