有没有一种方法可以在编译时检测编译器是否支持C++11的某些特性?例如,类似于这样的内容:
#ifndef VARIADIC_TEMPLATES_SUPPORTED
#error "Your compiler doesn't support variadic templates. :("
#else
template <typename... DatatypeList>
class Tuple
{
// ...
}
#endif
有一个名为__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线程和其他特定的标准部分。
__cplusplus
的值设置为201103L
,表示完全符合2011标准。它并不告诉你关于部分符合或编译器扩展的情况。如果__cplusplus
被设置为201103L
,那么要么编译器完全符合标准,要么它在欺骗你。如果不是,那么你无法确定它支持哪些功能。 - Keith Thompson__cplusplus
的值设置为199711L
,用于C++ 11。 - Donald Duck__cplusplus
设置为 199711L
的编译器并不符合 C++11 标准。它们可能有选项可以使它们正确地运行。 - Keith Thompson我知道这是一个非常古老的问题,但这个问题可能经常出现,并且答案有点过时。
使用C++14标准的新编译器有一种标准的方法来检查功能,包括C++11功能。一个全面的页面位于https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
总之,每个功能都有一个标准宏定义,您可以使用#ifdef
进行检查。例如,要检查用户定义的文字,您可以使用
#ifdef __cpp_user_defined_literals
__has_include()
宏。 - prapin#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
cout << "C++11 is supported";
#else
cout << "C++11 is not supported";
#endif
对于C++11,大多数编译器将__cplusplus
宏设置为201103L
。但是,视觉工作室根据其年龄和配置情况而定,将其设置为199711L
,这是其他编译器在C++11之前使用的值。
此代码将_cplusplus
宏与201103L
进行比较,适用于除Visual Studio以外的所有编译器。如果编译器是Visual Studio,则检查Visual Studio的版本是否晚于2015年,这是Visual Studio完全支持C++11的第一个版本(对于Visual Studio 2015,_MSC_VER
宏的值为1900
,请参见this answer)。
g++ -std=c++98
,它会错误地打印出“支持C++11”。 - pts为了支持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;
}
如果您不想使用Boost.Config,并且需要测试是否支持C++11的编译器,则可以检查常量__cplusplus
的值。但是,编译器可能支持C++11标准的大多数流行特性,但它并不支持全部规范。如果您想启用对尚未完全符合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
当这个问题在2011年2月被提出时,对于C++11的支持是不一致的。编译器需要时间来适应这个标准,因此在这段时间内,它们发布了部分支持。例如,一个编译器可能会实现可变参数模板,但不支持auto
。
如果你的代码依赖于C++11的一个子集,你没有一种标准的方法来询问编译器是否具体支持它们。
你可以check总体的C++11支持情况,使用#if __cplusplus >= 201103L
,但:
__cplusplus
设置为201103L
,而且没有人拥有全部特性支持。因此,如果你使用这个,你将不必要地拒绝大多数或全部人们想要用来编译你的代码的编译器。Boost.Config
的维护者跟踪哪些编译器支持哪些特性,并为每个Boost.Config
版本更新宏。#if __cplusplus >= 201103L
。(有关此宏的标准参考,请参见Paulo M的答案。)但请注意,MSVC存在一些问题,请参见Donald Duck的答案。
__cplusplus
宏之外,您还可以#include <version>
以获取一堆功能测试宏。这基本上是一个基于标准的替代方案Boost.Config
。<array>
头文件时,你可以使用#if __has_include(<array>)
。#if __cplusplus >= 201103L
会告诉你正在使用C++11,但其他设置,如Xcode中的标准库版本设置,可能仍然没有新库可用(大多数库在不同的名称下可用,如<tr1/array>
)。
template <typename... Test> struct compiler_must_support_variadic_templates;
这样的代码。如果存在语法错误,编译器会很快地报错。当然,最好还是提供一个更加详细的错误信息。 - GManNickG