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

标签 c++ c++11 clang

较新版本的 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

这些类似函数的宏采用单个标识符参数,即功能名称。 __has_feature 如果该功能同时受 Clang 支持并在当前语言标准中标准化,则评估为 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) 结合起来,并在 true 时使用新功能,否则在 false 时解决它。然后,当您升级 clang 或使用的语言模式发生变化时,您的代码将自动适应。

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

关于c++ - Clang 在 C++03 模式下支持哪些 C++11 扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15601745/

相关文章:

c++模板重载方法依赖于类类型

c++ - DeviceIoControl 缓冲区参数编码和对齐

c++ - 未包含自定义头文件

c++ - 模板参数包会引发错误,而显式参数不会

c++ - clang -cc1 和系统包括

c++ - 显式转换运算符和常量引用限定

C++ cout 十六进制格式

c++ - 我可以插入移动的容器吗

c++ - 在 (Neo)vim 中调试 C++

c++ - g++ 无法将 .o 文件链接到可执行文件