【问题标题】:What C++11 extensions does Clang support in C++03 mode?Clang 在 C++03 模式下支持哪些 C++11 扩展?
【发布时间】:2013-03-24 17:35:51
【问题描述】:

在 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&lt;int, int&gt; foo{{1,2},{3,4}};) 失败并出现语法错误。

就我而言,我有一个现有的不可变库,由于某些兼容性问题,它只能在 C++03 模式下编译;开发人员表示他们将在“不久的将来”支持 C++11。我现在想使用 C++11 功能针对这个库编写代码,这样当他们使他们的库与 C++11 兼容时,我就不必再次返回并“现代化”代码。 Clang 的 C++11 扩展似乎非常适合此目的,但我不确定我可以使用什么。 Clang 的 C++11 扩展是否记录在某处?

【问题讨论】:

    标签: c++ c++11 clang


    【解决方案1】:

    您可以在这里使用两个“功能测试”宏:

    __has_feature__has_extension

    这些类似函数的宏采用单个标识符参数,即功能名称。 __has_feature 如果该功能同时受 Clang 支持并在当前语言标准中标准化,则评估为 1,否则为 0,而 __has_extension 如果当前语言中的 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()
    {
    }
    

    对我来说,使用 -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 版本的最快和最准确的方法。

    【讨论】:

    • 不错!我写了一个小程序来列出所有的特性。从 Clang 4.2 开始,似乎支持已删除函数、内联命名空间、本地类型模板参数、覆盖控制关键字、引用限定函数、范围右值引用
    • 奇怪的是__has_extension(cxx_auto_type) 是假的,但是(正如您在我的示例中看到的)auto &amp;i 编译得很好。
    • @nneonneo:似乎在 Clang 3.3(开发版)中,所有测试都编译为“true”,cxx_inheriting_constructors 除外。根据their table 的说法,似乎thread_local 也将在下一个版本中丢失。但它越来越接近了。我想他们不会让 __has_extension 评估为 true,直到支持确定且稳定,这就是为什么 cxx_auto_type 在代码工作时可能评估为 false。
    • @MikaelPersson 我们不会让 __has_extension(cxx_auto_type) 在 C++98 模式下评估为真,因为在 C++98 模式下存在一些极端情况,我们会拒绝正确使用 auto类型(因为我们将其视为 auto 存储类说明符)。
    猜你喜欢
    • 2011-12-20
    • 1970-01-01
    • 2012-11-01
    • 2015-03-01
    • 2012-05-23
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多