__has_cpp_attribute 不是 'function-like' 宏?
__has_cpp_attribute not a 'function-like' macro?
我正在尝试将 [[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]]
属性的正确方法是什么?
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
则跳过的组中。 (在跳过的组中时,预处理指令仅通过指令名称进行处理;其余标记将被忽略。)
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
宏。它目前支持使用弃用属性的 GCC 4.5+、ICC 13+、armcc 4.1+ 和 TI 7.3+,使用弃用的 declspec 的 MSVC 13.10+ 和 Pelles 6.50+,以及使用 pragma 的 IAR,但支持可能会扩展到时间,我可能不会更新这个答案。
我正在尝试将 [[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]]
属性的正确方法是什么?
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
则跳过的组中。 (在跳过的组中时,预处理指令仅通过指令名称进行处理;其余标记将被忽略。)
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
宏。它目前支持使用弃用属性的 GCC 4.5+、ICC 13+、armcc 4.1+ 和 TI 7.3+,使用弃用的 declspec 的 MSVC 13.10+ 和 Pelles 6.50+,以及使用 pragma 的 IAR,但支持可能会扩展到时间,我可能不会更新这个答案。