在C ++ 03模式下编译时,较新版本的Clang支持某些C ++ 11扩展,但可能会在-Wc++11-extensions
打开时发出警告。例如,编译此代码:
std::map<int, int> foo;
for(auto &i : foo) {
}
带有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) {
但编译成功并生成了正确的代码。但是,尝试使用例如统一初始化(std::map<int, int> foo{{1,2},{3,4}};
)因语法错误而失败。
就我而言,我有一个现有的不可变库,由于某些兼容性问题,它只能在C ++ 03模式下编译;开发人员表示他们将在“不久的将来”支持C ++ 11。我想现在使用C ++ 11的功能编写针对这个库的代码,这样我就不必在代码与C ++ 11兼容时再回过头来“现代化”代码。 Clang的C ++ 11扩展似乎很适合这个目的,但我不确定我能用什么。 Clang的C ++ 11扩展是否记录在哪里?
答案 0 :(得分:7)
您可以在此处使用两个“功能测试”宏:
__has_feature
和__has_extension
这些类似函数的宏采用单个标识符参数,该参数是功能的名称。如果Clang支持该功能并且在当前语言标准中标准化,则__has_feature
计算结果为1,否则计算结果为0;如果当前语言的Clang支持该功能,则__has_extension
计算结果为1(或者#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()
{
}
作为语言扩展或标准语言特征)或如果不是,则为0。
这些宏和标识符记录在这里:
http://clang.llvm.org/docs/LanguageExtensions.html
在您的具体示例中,以下HelloWorld提供的信息最多:
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.
对我来说,使用-std = c ++ 03输出:
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.
而使用-std = c ++ 11,输出变为:
__has_extension(cxx_generalized_initializers)
对于您的用例,您可以使用{{1}}对代码进行处理,并在true时使用新功能,否则在处理时将其解决。然后,当您升级clang时,或者在使用的语言模式发生变化时,您的代码将自动适应。
至于支持哪种语言功能,哪种语言功能不支持,文档可能有所帮助,但我发现编写上述测试是评估当前clang版本的最快,最准确的方法。