111

Is there a way to detect at compile-time if the compiler supports certain 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
Maxpm
  • 24,113
  • 33
  • 111
  • 170
  • 2
    You could have a header called "assert_variadic_template_support.hpp" that you can include and within do something like `template struct compiler_must_support_variadic_templates;`. A syntax error would quickly reveal the problem. (Just as an aside, a proper error message is much better.) – GManNickG Feb 19 '11 at 00:53
  • The 'right' way to solve this problem is a configure test. – Joseph Garvin Dec 18 '11 at 02:40

9 Answers9

126

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.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Cygon
  • 9,444
  • 8
  • 42
  • 50
  • 42
    C++11 sets the value of `__cplusplus` to `201103L`. That asserts full conformance to the 2011 standard; it doesn't tell you about partial conformance or compiler extensions. If `__cplusplus` is set to `201103L`, then either the compiler fully conforms or it's lying to you. If it's not, then you can't really tell which features it supports. – Keith Thompson May 16 '13 at 17:24
  • 1
    g++ 4.7.x (and presumably newer) sets this when `-std=c++11` option is specified (may also with `-std=gnu++11`). They do this, even though they are not quite feature complete (4.8 brings us a lot closer). Note - there is a gap between what the compiler supports and what's available in the standard library. Both 4.7.x & 4.8.x are currently missing regex support - but that's a library, not a compiler feature. – Nathan Ernst May 16 '13 at 20:02
  • 1
    I wonder why this is not the accepted answer. Also, you could use [this suggestion](http://stackoverflow.com/questions/5047971/how-do-i-check-for-c11-support#comment23849959_10849807) to further improve your answer, it's very good. – Iharob Al Asimi Jul 04 '15 at 19:23
  • 1
    @KeithThompson For me, both Code::Blocks and Visual Studio set the value of `__cplusplus` to `199711L` for C++ 11. – Donald Duck Nov 09 '16 at 14:21
  • 3
    @DonaldDuck: Strictly speaking, no, they don't. A compiler that sets `__cplusplus` to `199711L` is not a conforming C++11 compiler. They probably have options to make them behave correctly. – Keith Thompson Nov 09 '16 at 15:47
  • This answer makes no sense; why would we look for 1997, if we need to test for C++11 support. C++ was first standardized in 1998, so every C++ compiler should be setting this to at least 199711 if it conforms to any version of ISO C++ at all. – Kaz Dec 03 '20 at 17:00
  • Regarding *"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."* The assumption should be that the OP wants a test of a decently high confidence for C++11. If the vendors are not bold enough to announce C++11 support via `__cplusplus`, then the confidence level is poor. Some C++11 feature the program depends on might in fact not be there. – Kaz Dec 03 '20 at 17:07
  • 199711L was the best available information at the time. In Stroustrup's own words: "In C++11 the macro __cplusplus will be set to a value that differs from (is greater than) the current 199711L. " - feel free to give an up-vote to more recent answers with the actual constant used in the finalized standard, I'll do the same! | Adoption happens incrementally, so I think it was fair to mention Boost for more granular checking :) – Cygon Dec 05 '20 at 08:38
42

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.

Paolo M
  • 12,403
  • 6
  • 52
  • 73
  • 2
    For example, static_assert is supported in VS2010 and in all c++11 copilers. So, if you check for a value of __cplusplus greater or equal than the one set in VS2010 (i.e. >= 199711L), you can be fine. – Paolo M Apr 02 '15 at 07:25
36

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
Jarryd
  • 1,312
  • 11
  • 17
  • 2
    I didn't know that. I think that this simple feature is coming late, but still can be very useful, especially the `__has_include()` macro. – prapin Jul 25 '16 at 19:13
27

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

Maxpm
  • 24,113
  • 33
  • 111
  • 170
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
25

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;
}
kurono267
  • 301
  • 4
  • 3
7

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

Community
  • 1
  • 1
Vamshi Krishna
  • 119
  • 4
  • 7
  • This test will succeed in any C++ compiler that conforms to C++98 or later and that is not the Microsoft C++ compiler. – Kaz Dec 03 '20 at 17:12
6

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.

diverscuba23
  • 2,165
  • 18
  • 32
  • 2
    Yes autoconf can be used to test for features but it you must make it generate the appropriate macro for failure or successes that can then be tested by the code above. So by itself this answer adds no information. – Martin York Feb 19 '11 at 03:26
  • 3
    @LokiAstari: That's not how autoconf works. Autoconf provides macros that let you have your configure script compile a test source file and set the #define to 0 or 1 based on the success of the compilation. diverscuba23's answer provides information by pointing out the OP is reaching for a suboptimal solution to the real problem. – Joseph Garvin Dec 18 '11 at 02:44
  • 1
    http://stackoverflow.com/q/11909347/580412 https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html – phs Aug 27 '15 at 00:56
4

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.

Maxpm
  • 24,113
  • 33
  • 111
  • 170
  • I really wish there were additional macros which specify the respective version number assigned to a given standard. I.e., I wish the next C++ ISO standard would specify e.g.__cplusplus1998 as 199711L, __cplusplus2011 as 201103L, __cplusplus2014 as 201402L etc. Each new standard would add its own macro to the list. I have to look the values up every time I want to use one, and it is too easy to make typos. – Peter - Reinstate Monica Jul 07 '23 at 16:02
1

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

yairchu
  • 23,680
  • 7
  • 69
  • 109