我试图将[[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]]
属性的正确方法是什么?
答案 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,但支持范围可能会扩大时间,我可能不会更新此答案。