有没有一种方法可以在编译时检测编译器是否支持C ++ 11的某些功能? 例如,如下所示:
#ifndef VARIADIC_TEMPLATES_SUPPORTED
#error"Your compiler doesn't support variadic templates. :("
#else
template
class Tuple
{
// ...
}
#endif
您可以包含一个名为" assert_variadic_template_support.hpp"的标头,并且可以在其中执行类似template struct compiler_must_support_variadic_templates;的标头。 语法错误将迅速揭示该问题。 (顺便说一句,正确的错误消息要好得多。)
解决此问题的正确方法是配置测试。
有一个名为__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线程和标准其他特定部分的支持的唯一明智的方法。
C ++ 11将__cplusplus的值设置为201103L。声称完全符合2011年标准;它不会告诉您有关部分一致性或编译器扩展的信息。如果__cplusplus设置为201103L,则编译器完全符合要求或对您说谎。如果它不支持,那么您就无法确定它支持哪些功能。
当指定了-std=c++11选项(可能也使用-std=gnu++11)时,g ++ 4.7.x(可能是较新的版本)对此进行了设置。即使它们的功能还不够完善,他们也会这样做(4.8使我们更加接近)。注意-编译器支持的功能与标准库中的功能之间存在差距。 4.7.x和4.8.x当前都缺少对正则表达式的支持-但这就是库,而不是编译器功能。
我不知道为什么这不是公认的答案。另外,您可以使用此建议进一步完善您的答案,这非常好。
@KeithThompson对我来说,对于C ++ 11,Code :: Blocks和Visual Studio都将__cplusplus的值设置为199711L。
@DonaldDuck:严格来说,不,他们没有。将__cplusplus设置为199711L的编译器不是合格的C ++ 11编译器。他们可能有使其正确行为的选项。
Boost.Config有大量的宏,可用于测试对特定C ++ 11功能的支持。
它们如何工作?还是仅仅是典型的Boost黑魔法?
@Maxpm:在大多数情况下,Boost的维护者只会跟踪哪些编译器支持哪些功能并为每个版本更新宏。它很容易检测您正在编译的编译器。确实,这没什么令人兴奋的:只需花费一些时间就可以列出谁支持什么。
正如C ++ 11标准(第16.8节)所述:
The name __cplusplus is defined to the value 201103L when
compiling a C++ translation unit.
使用该宏的值,您可以检查编译器是否符合C ++ 11。
现在,如果您正在寻找一种标准的方法来检查编译器是否支持C ++ 11功能的任何子集,那么我认为没有标准的可移植方法。您可以查看编译器文档或std库头文件以获取更多信息。
例如,VS2010和所有c ++ 11编译器均支持static_assert。因此,如果您检查__cplusplus的值是否大于或等于VS2010中设置的值(即> = 199711L),就可以了。
我知道这是一个非常老的问题,但是可能经常会看到这个问题,而且答案有些过时了。
符合C ++ 14标准的较新编译器具有检查功能(包括C ++ 11功能)的标准方法。完整的页面位于https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
总之,每个功能都有一个定义的标准宏,您可以使用#ifdef进行检查。例如,要检查用户定义的文字,可以使用
#ifdef __cpp_user_defined_literals
我不知道。我认为这个简单的功能来晚了,但是仍然非常有用,尤其是__has_include()宏。
对于检查支持C ++ 14等。在GCC 5.2.1上进行测试。
#include
int main(){
#if __cplusplus==201402L
std::cout <
#elif __cplusplus==201103L
std::cout <
#else
std::cout <
#endif
return 0;
}
我只是编写了一个小型测试套件,以检查特定编译器支持哪些C ++ 11功能。但是,这当然是"预编译时"检查。
https://github.com/sloede/cxx11tests
您可以使用此:
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
cout <
#else
cout <
#endif
对于C ++ 11,除Visual Studio之外,大多数编译器都将__cplusplus宏设置为201103L,但是任何Visual Studio版本都将其设置为199711L,这是C ++ 11之前的其他编译器所使用的值。对于除Visual Studio以外的所有编译器,此代码将_cplusplus宏与201103L进行比较,并且如果编译器为Visual Studio,它将检查Visual Studio的版本是否晚于2015年(Visual Studio的第一个完全支持C的版本)。 ++ 11(对于Visual Studio 2015,_MSC_VER宏的值为1900,请参见此答案)。
这个答案是不正确的。对于带有GCC 4.8的g++ -std=c++98,它会错误地打印C++11 is supported。
@pts对不起,只是一个错字。现在应该修复。
如果您不想使用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编译器版本的完整列表。
在传统的Linux / Unix世界中,传统上使用autoconf来测试库和编译器功能的存在以及将它们放入需要时在文件中使用的config.h中的错误。
是的,可以使用autoconf来测试功能,但是必须使它为失败或成功生成适当的宏,然后可以通过上面的代码对其进行测试。因此,这个答案本身不会增加任何信息。
@LokiAstari:那不是autoconf的工作原理。 Autoconf提供的宏可让您让配置脚本编译测试源文件,并根据编译成功将#define设置为0或1。 diverscuba23s的答案通过指出OP正在寻求针对实际问题的次佳解决方案来提供信息。
stackoverflow.com/q/11909347/580412 gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
如果检查的是C ++ 11库的可用性(不是语言功能),例如标头,则可以#if __has_include()。
有时检查#if __cplusplus >= 201103L会告诉您您使用的是C ++ 11,但其他设置(例如Xcode中的标准库版本设置)可能仍然没有可用的新库(其中大多数以不同的名称提供,例如)