I am attempting to introduce the [[deprecated]]
attribute into my codebase. However, not all the compilers I am required to support have support for this syntax yet (the various method used by different compilers before standardization are described in the attribute standardization proposal N2761). Thus, I am attempting to conditionally compile in this attribute, using the __has_cpp_attribute
macro-like function first, if it is available, like so:
#if defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated)
#define DEPRECATED(msg) [[deprecated(msg)]]
#elif OTHER_COMPILER
// ...
#endif
However, I'm getting errors when compiling this I am using gcc version 4.9.2 (GCC)
, command line 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)
This error seems to indicate that __has_cpp_attribute
is defined, but that it is not a macro function. What is the proper way to conditionally compile the [[deprecated]]
attribute in gcc?
GCC 4.9 doesn't have __has_cpp_attribute
, and the short-circuiting behavior of &&
does not extend to allowing invalid constructs to follow it.
That is to say, if foo
isn't defined,
#if defined(foo) && foo(bar)
is not valid.
What you want is
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(deprecated)
#define DEPRECATED(msg) [[deprecated(msg)]]
#endif
#elif OTHER_COMPILER
// ...
#endif
so that the condition using __has_cpp_attribute
is in a group that is skipped if __has_cpp_attribute
is not defined. (When in a group that is skipped, preprocessing directives are only processed through the directive's name; the remaining tokens are ignored.)
T.C.'s answer is right, I wanted to add that you can also define a wrapper for __has_cpp_attribute
, which tends to make multiple tests easier to write
#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
If you go this route, please use a namespace instead of defining __has_cpp_attribute
. Other code will check to see if defined(__has_cpp_attribute)
and use it if available or fall back on checking compiler versions if it isn't. Defining __has_cpp_attribute
will break that.
Of course, a lot of other compilers support some kind of syntax for marking symbols as deprecated even if they don't support __has_cpp_attribute
, so you'll probably end up with a lot more cases; see the HEDLEY_DEPRECATED
macro in Hedley. It currently supports GCC 4.5+, ICC 13+, armcc 4.1+, and TI 7.3+ using the deprecated attribute, MSVC 13.10+ and Pelles 6.50+ using the deprecated declspec, and IAR using a pragma, but it's likely that support will expand over time and I probably won't update this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With