如何检查C ++ 11支持?


104

有没有一种方法可以在编译时检测编译器是否支持C ++ 11的某些功能?例如,如下所示:

#ifndef VARIADIC_TEMPLATES_SUPPORTED

#error "Your compiler doesn't support variadic templates.  :("

#else

template <typename... DatatypeList>
class Tuple
{
    // ...
}

#endif

2
您可以包含一个名为“ assert_variadic_template_support.hpp”的标头,并可以在其中进行类似的操作template <typename... Test> struct compiler_must_support_variadic_templates;。语法错误将迅速揭示该问题。(
顺便说一句

解决此问题的“正确”方法是配置测试。
Joseph Garvin

Answers:


125

有一个名为常量__cplusplus是C ++编译器应设置为C版本++标准支持的看到这

#if __cplusplus <= 199711L
  #error This library needs at least a C++11 compliant compiler
#endif

在Visual Studio 2010 SP1中将其设置为199711L,但是我不知道供应商是否会大胆地增加它(如果它们仅具有(部分)编译器级别的支持,而不是具有所有C ++ 11更改的标准C ++库) 。

因此,另一个答案中提到的Boost的定义仍然是弄清楚是否存在例如对C ++ 11线程和标准其他特定部分的支持的唯一明智的方法。


37
C ++ 11将的值设置__cplusplus201103L。声称完全符合2011年标准;它不会告诉您有关部分一致性或编译器扩展的信息。如果__cplusplus将设置为201103L,则编译器完全符合要求或对您说谎。如果不是,那么您就无法确定它支持哪些功能。
基思·汤普森

1
g ++ 4.7.x(可能是更新的)在-std=c++11指定option 时设置了此设置(也可以使用-std=gnu++11)。即使它们的功能还不够完善,他们也会这样做(4.8使我们更加接近)。注意-编译器支持的内容与标准库中的可用内容之间存在差距。4.7.x和4.8.x当前都缺少正则表达式支持-但这是一个库,而不是编译器功能。
内森·恩斯特

1
我不知道为什么这不是公认的答案。另外,您可以使用此建议进一步改善您的答案,这非常好。
Iharob Al Asimi

1
@KeithThompson对我来说,这两个代码::块和Visual Studio设置的值__cplusplus,以199711L用于C ++ 11
唐老鸭

3
@DonaldDuck:严格来说,不,他们没有。设置__cplusplus为的编译器199711L不是合格的C ++ 11编译器。他们可能有使其正确行为的选项。
基思·汤普森

39

C ++ 11标准(第16.8节)所述:

编译C ++转换单元时,名称__cplusplus定义为值201103L

使用该宏的值,您可以检查编译器是否符合C ++ 11。

现在,如果您正在寻找一种标准的方法来检查编译器是否支持C ++ 11功能的任何子集,那么我认为没有标准的可移植方法。您可以查看编译器文档或std库头文件以获取更多信息。


2
例如,VS2010和所有c ++ 11编译器均支持static_assert。因此,如果您检查__cplusplus的值大于或等于VS2010中设置的值(即> = 199711L),则可以。
Paolo M

33

我知道这是一个很老的问题,但是这个问题可能经常出现,答案有些过时。

符合C ++ 14标准的较新编译器具有检查功能(包括C ++ 11功能)的标准方法。完整的页面位于https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations

总之,每个功能都有一个定义的标准宏,您可以使用进行检查#ifdef。例如,要检查用户定义的文字,可以使用

#ifdef __cpp_user_defined_literals

1
我不知道 我认为这个简单的功能来晚了,但仍然会非常有用,尤其是__has_include()宏。
prapin 2016年

22

对于检查支持C ++ 14等。在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;
}

17

您可以使用此:

#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
    cout << "C++11 is supported";
#else
    cout << "C++11 is not supported";
#endif

对于C ++ 11,除Visual Studio之外,大多数编译器都将__cplusplus宏设置为201103L,但是Visual Studio的任何版本都将其设置199711L为C ++ 11之前其他编译器使用的值。此代码将_cplusplus宏与201103L除Visual Studio以外的所有编译器进行比较,并且如果编译器为Visual Studio,它将检查Visual Studio的版本是否晚于2015年,Visual Studio是第一个完全支持C ++ 11的版本(适用于Visual Studio)。在Studio 2015中,_MSC_VER宏具有值1900,请参见此答案)。


1
这个答案是不正确的。对于g++ -std=c++98GCC 4.8,它打印不正确C++11 is supported
pt

1
@pts对不起,只是一个错字。现在应该修复。
唐老鸭

7

如果您不想使用Boost.Config并且需要测试支持C ++ 11的编译器,则可以检查常量的值__cplusplus。但是,编译器可能支持C ++ 11标准的大多数流行功能,但不支持整个规范。如果要启用对尚未100%兼容C ++ 11规范的特定Visual Studio编译器的支持,请使用以下代码段,该代码段允许在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

如何检测我是否正在使用Visual Studio 2008编译代码,提供了Visual Studio编译器版本的完整列表。


6

在传统的Linux / Unix世界中,传统上使用autoconf来测试库和编译器功能的存在以及将它们放入需要时在文件中使用的config.h中的错误。


2
是的,可以使用autoconf来测试功能,但是您必须使它为失败或成功生成适当的宏,然后可以通过上面的代码进行测试。因此,这个答案本身不会增加任何信息。
马丁·约克

3
@LokiAstari:这不是autoconf的工作原理。Autoconf提供的宏使您可以让配置脚本编译测试源文件,并根据编译成功将#define设置为0或1。diverscuba23的答案通过指出OP正在寻求针对实际问题的次佳解决方案来提供信息。
Joseph Garvin


1

如果检查的是C ++ 11库的可用性(不是语言功能),例如<array>标头,则可以#if __has_include(<array>)

有时检查#if __cplusplus >= 201103L会告诉您您使用的是C ++ 11,但其他设置(例如Xcode中的标准库版本设置)可能仍然没有可用的新库(其中大多数以不同的名称提供,例如<tr1/array>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.