Clang在C++ 03模式下支持哪些C++ 11扩展?

nne*_*neo 3 c++ clang c++11

在C++ 03模式下编译时,较新版本的Clang支持某些C++ 11扩展,但可能会在-Wc++11-extensions打开时发出警告.例如,编译此代码:

std::map<int, int> foo;
for(auto &i : foo) {
}
Run Code Online (Sandbox Code Playgroud)

clang test.cpp -std=c++03这些警告的结果:

test.cpp:5:6: warning: 'auto' type specifier is a C++11 extension
      [-Wc++11-extensions]
        for(auto &i : foo) {
            ^
test.cpp:5:14: warning: range-based for loop is a C++11 extension
      [-Wc++11-extensions]
        for(auto &i : foo) {
Run Code Online (Sandbox Code Playgroud)

但编译成功并生成正确的代码.但是,尝试使用例如统一初始化(std::map<int, int> foo{{1,2},{3,4}};)会因语法错误而失败.

在我的情况下,我有一个现有的,不可变的库,由于一些兼容性问题,只能在C++ 03模式下编译; 开发人员表示他们将在"不久的将来"支持C++ 11.我想现在使用C++ 11的功能编写针对这个库的代码,这样我就不必在代码与C++ 11兼容时再回过头来"现代化"代码.Clang的C++ 11扩展似乎很适合这个目的,但我不确定我能用什么.Clang的C++ 11扩展是否记录在某处?

How*_*ant 7

您可以在此处使用两个"功能测试"宏:

__has_feature__has_extension

这些类似函数的宏采用单个标识符参数,该参数是功能的名称.__has_feature如果Clang支持该功能并在当前语言标准中标准化,则__has_extension评估为1;如果不支持,则评估为0;如果Clang支持当前语言(作为语言扩展或标准语言功能),则评估为1或者如果不是0.

这些宏和标识符记录在这里:

http://clang.llvm.org/docs/LanguageExtensions.html

在您的具体示例中,以下HelloWorld提供的信息量最大:

#if __has_extension(cxx_generalized_initializers)
#warning __has_extension(cxx_generalized_initializers) is true
#else
#warning __has_extension(cxx_generalized_initializers) is false
#endif

#if __has_feature(cxx_generalized_initializers)
#warning __has_feature(cxx_generalized_initializers) is true
#else
#warning __has_feature(cxx_generalized_initializers) is false
#endif

#if __has_extension(cxx_range_for)
#warning __has_extension(cxx_range_for) is true
#else
#warning __has_extension(cxx_range_for) is false
#endif

#if __has_feature(cxx_range_for)
#warning __has_feature(cxx_range_for) is true
#else
#warning __has_feature(cxx_range_for) is false
#endif

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

对我来说,使用-std = c ++ 03输出:

test.cpp:4:2: warning: __has_extension(cxx_generalized_initializers) is false [-W#warnings]
#warning __has_extension(cxx_generalized_initializers) is false
 ^
test.cpp:10:2: warning: __has_feature(cxx_generalized_initializers) is false [-W#warnings]
#warning __has_feature(cxx_generalized_initializers) is false
 ^
test.cpp:14:2: warning: __has_extension(cxx_range_for) is true [-W#warnings]
#warning __has_extension(cxx_range_for) is true
 ^
test.cpp:22:2: warning: __has_feature(cxx_range_for) is false [-W#warnings]
#warning __has_feature(cxx_range_for) is false
 ^
4 warnings generated.
Run Code Online (Sandbox Code Playgroud)

而使用-std = c ++ 11,输出变为:

test.cpp:2:2: warning: __has_extension(cxx_generalized_initializers) is true [-W#warnings]
#warning __has_extension(cxx_generalized_initializers) is true
 ^
test.cpp:8:2: warning: __has_feature(cxx_generalized_initializers) is true [-W#warnings]
#warning __has_feature(cxx_generalized_initializers) is true
 ^
test.cpp:14:2: warning: __has_extension(cxx_range_for) is true [-W#warnings]
#warning __has_extension(cxx_range_for) is true
 ^
test.cpp:20:2: warning: __has_feature(cxx_range_for) is true [-W#warnings]
#warning __has_feature(cxx_range_for) is true
 ^
4 warnings generated.
Run Code Online (Sandbox Code Playgroud)

对于您的用例,您可以__has_extension(cxx_generalized_initializers)使用正确的代码并使用新功能,否则在错误时解决它.然后,当您升级clang时,或者随着所使用的语言模式的更改,您的代码将自动适应.

至于支持哪种语言功能,哪些不支持,文档可能会有所帮助,但我发现编写一个测试,如上面是评估我目前的clang版本的最快,最准确的方法.