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

What C++11 extensions does Clang support in C++03 mode?

本文关键字:c++ 扩展 模式 Clang 支持      更新时间:2023-10-16

新版本的Clang在c++ 03模式下编译时支持某些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扩展有文档记录吗?

你可以在这里使用两个"特性测试"宏:

__has_feature__has_extension

这些类函数的宏接受一个标识符参数,即一个特性的名称。如果Clang支持该特性并将其标准化,__has_feature的值为1,如果不支持则为0;如果Clang在当前语言中支持该特性(作为语言扩展或标准语言特性),__has_extension的值为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()
{
}

对于我来说,使用-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.

而使用-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.

对于您的用例,您可以将代码设置为__has_extension(cxx_generalized_initializers),并在为真时使用新特性,否则在为假时绕过它。当您升级clang或使用的语言模式发生变化时,您的代码将自动适应。

至于支持哪些语言特性,哪些不支持,文档可能会有所帮助,但我发现编写这样的测试是评估当前clang版本的最快和最准确的方法。