__has_cpp_attribute不是'类似函数'宏?

时间:2015-05-22 17:50:05

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

我试图将[[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]]属性的正确方法是什么?

2 个答案:

答案 0 :(得分:11)

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时跳过的组中。 (在跳过的组中,预处理指令仅通过指令的名称处理;其余的标记将被忽略。)

答案 1 :(得分:0)

T.C。的答案是正确的,我想补充一点,您还可以为#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_DEPRECATED的某种语法来将符号标记为已弃用,因此您可能会遇到更多的情况。请参见Hedley中的function getStringDateTime(date) { var a = date.getFullYear(); var m = date.getMonth() + 1; var d = date.getDate(); var h = date.getHours(); var mi = date.getMinutes(); var strDate = a + (m < 10 ? '0' : '') + m + (d < 10 ? '0' : '') + d + ' ' + (h < 10 ? '0' + h : h) + ':' + (mi < 10 ? '0' + mi : mi); return strDate; } console.log(getStringDateTime(new Date()))宏。目前,它使用不赞成使用的属性支持GCC 4.5 +,ICC 13 +,armcc 4.1+和TI 7.3+,使用不赞成使用的declspec支持MSVC 13.10+和Pelles 6.50+,以及使用编译指示的IAR,但支持范围可能会扩大时间,我可能不会更新此答案。