开发者

How do I check for C++11 support?

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 to 201103L 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>)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜