【问题标题】:__has_cpp_attribute not a 'function-like' macro?__has_cpp_attribute 不是“类函数”宏?
【发布时间】:2015-08-04 20:16:57
【问题描述】:

我正在尝试将[[deprecated]] 属性引入我的代码库。但是,并非我需要支持的所有编译器都支持这种语法(在标准化之前不同编译器使用的各种方法在attribute standardization proposal N2761 中进行了描述)。因此,我尝试在此属性中进行有条件地编译,首先使用__has_cpp_attribute 类宏函数(如果可用),如下所示:

#if defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated)
    #define DEPRECATED(msg) [[deprecated(msg)]]
#elif OTHER_COMPILER
    // ...
#endif

但是,我在使用gcc version 4.9.2 (GCC),命令行gcc -std=c++14 cpp.cpp进行编译时遇到错误:

cpp.cpp:1:56: error: missing binary operator before token "("
#if defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated)

此错误似乎表明__has_cpp_attribute 已定义,但它不是宏函数。在 gcc 中有条件地编译 [[deprecated]] 属性的正确方法是什么?

【问题讨论】:

  • @T.C.哦,它没有功能测试宏?
  • @Columbo 我在 gcc 5.1 发行说明中看到:gnu.org/software/gcc/gcc-5/changes.html,它说添加了__has_cpp_attribute;所以我认为它在那之前不存在。

标签: c++ gcc macros c++14


【解决方案1】:

GCC 4.9 没有__has_cpp_attribute,&& 的短路行为不会扩展到允许无效构造跟随它。

也就是说,如果没有定义foo,

#if defined(foo) && foo(bar)

无效。

你想要的是

#if defined(__has_cpp_attribute) 
    #if __has_cpp_attribute(deprecated)
        #define DEPRECATED(msg) [[deprecated(msg)]]
    #endif
#elif OTHER_COMPILER
    // ...
#endif

因此使用__has_cpp_attribute 的条件位于如果__has_cpp_attribute 未定义则被跳过的组中。 (当在一个被跳过的组中时,预处理指令仅通过指令的名称进行处理;其余的标记被忽略。)

【讨论】:

    【解决方案2】:

    T.C. 的回答是对的,我想补充一点,您还可以为__has_cpp_attribute 定义一个包装器,这往往会使多个测试更容易编写

    #if defined(__has_cpp_attribute)
    #  define MY_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
    #else
    #  define MY_HAS_CPP_ATTRIBUTE(attr) (0)
    #endif
    
    #if MY_HAS_CPP_ATTRIBUTE(attr)
    #  define MY_DEPRECATED [[deprecated(msg)]]
    #else
    #  define MY_DEPRECATED
    #endif
    

    如果你走这条路,请使用命名空间而不是定义__has_cpp_attribute。其他代码将检查defined(__has_cpp_attribute) 是否可用,如果可用则使用它,如果不可用则返回检查编译器版本。定义 __has_cpp_attribute 将打破这一点。

    当然,许多其他编译器支持某种将符号标记为已弃用的语法,即使它们不支持__has_cpp_attribute,所以您最终可能会遇到更多情况;参见Hedley 中的HEDLEY_DEPRECATED 宏。它目前支持使用 deprecated 属性的 GCC 4.5+、ICC 13+、armcc 4.1+ 和 TI 7.3+,使用 declspec 的 MSVC 13.10+ 和 Pelles 6.50+,以及使用 pragma 的 IAR,但支持可能会扩展到时间,我可能不会更新这个答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      • 2023-03-21
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多