181

I have a method in a C++ interface that I want to deprecate, with portable code.

When I Googled for this all I got was a Microsoft specific solution; #pragma deprecated and __declspec(deprecated).

If a general or fully-portable deprecation solution is not available, I will accept as a "second prize solution" one that can be used multiple specific compilers, like MSVC and a GCC.

7 Answers 7

248

In C++14, you can mark a function as deprecated using the [[deprecated]] attribute (see section 7.6.5 [dcl.attr.deprecated]).

The attribute-token deprecated can be used to mark names and entities whose use is still allowed, but is discouraged for some reason.

For example, the following function foo is deprecated:

[[deprecated]] void foo(int); 

It is possible to provide a message that describes why the name or entity was deprecated:

[[deprecated("Replaced by bar, which has an improved interface")]] void foo(int); 

The message must be a string literal.

For further details, see “Marking as deprecated in C++14”.

Sign up to request clarification or add additional context in comments.

4 Comments

Can you use [[deprecated]] in a macro?
@Zammbi You should be able to, as macro is handled by the preprocessor before compilation. [[deprecated]] should appear (and let the compiler output related warnings) where the macro is evaluated.
And how about C++11?
#define GRIKIFY(x) if (x) Grike(x) how can I mark this GRIKIFY macro as deprecated?
131

This should do the trick:

#ifdef __GNUC__ #define DEPRECATED(func) func __attribute__ ((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED(func) __declspec(deprecated) func #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED(func) func #endif ... //don't use me any more DEPRECATED(void OldFunc(int a, float b)); //use me instead void NewFunc(int a, double b); 

However, you will encounter problems if a function return type has a commas in its name e.g. std::pair<int, int> as this will be interpreted by the preprocesor as passing 2 arguments to the DEPRECATED macro. In that case you would have to typedef the return type.

Edit: simpler (but possibly less widely compatible) version here.

13 Comments

Instead of #error, it would be better to #define DEPRECATED(func) func
mxp: The deprecation is only a warning, and hence I'd say that a warning that it isn't supported is all you need.
Yep, I'd go for "#warning You need to implement DEPRECATED for this compiler", or some such. If that's impossible, then the porter can #define DEPRECATED(FUNC) FUNC, and live without it.
Unfortunately there's no standard way to output a compile warning in C++ :P #pragma message will have to do.
gcc's attribute syntax allows for the attribute to be in the same places as __declspec(deprecated) now, so the macro can be simplified.
|
67

Here's a simplified version of my 2008 answer:

#if defined(__GNUC__) || defined(__clang__) #define DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED __declspec(deprecated) #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED #endif //... //don't use me any more DEPRECATED void OldFunc(int a, float b); //use me instead void NewFunc(int a, double b); 

See also:

10 Comments

How do you [[deprecate]] your deprecated macros? :-)
I can't see any significant difference between those two answers. Why did you post it a second time?
You don't have to wrap it around the function so it's DEPRECATED void foo(...); instead of DEPRECATED(void foo(...));
You should have edited your 2008 answer rather than posting a new one.
This may not be as widely compatible as my other answer, hence I added this separately.
|
23

In GCC you can declare your function with the attribute deprecated like this:

void myfunc() __attribute__ ((deprecated)); 

This will trigger a compile-time warning when that function is used in a .c file.

You can find more info under "Diagnostic pragmas" at http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

Comments

14

Here is a more complete answer for 2018.

These days, a lot of tools allow you to not just mark something as deprecated, but also provide a message. This allows you to tell people when something was deprecated, and maybe point them toward a replacement.

There is still a lot of variety in compiler support:

  • C++14 supports [[deprecated]]/[[deprecated(message)]].
  • __attribute__((deprecated)) is supported by GCC 4.0+ and ARM 4.1+
  • __attribute__((deprecated)) and __attribute__((deprecated(message))) is supported for:
    • GCC 4.5+
    • Several compilers which masquerade as GCC 4.5+ (by setting __GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__)
    • Intel C/C++ Compiler going back to at least 16 (you can't trust __GNUC__/__GNUC_MINOR__, they just set it to whatever version of GCC is installed)
    • ARM 5.6+
  • MSVC supports __declspec(deprecated) since 13.10 (Visual Studio 2003)
  • MSVC supports __declspec(deprecated(message)) since 14.0 (Visual Studio 2005)

You can also use [[gnu::deprecated]] in recent versions of clang in C++11, based on __has_cpp_attribute(gnu::deprecated).

I have some macros in Hedley to handle all of this automatically which I keep up to date, but the current version (v2) looks like this:

#if defined(__cplusplus) && (__cplusplus >= 201402L) # define HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]] # define HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]] #elif \ HEDLEY_GCC_HAS_EXTENSION(attribute_deprecated_with_message,4,5,0) || \ HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \ HEDLEY_ARM_VERSION_CHECK(5,6,0) # define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) # define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) #elif \ HEDLEY_GCC_HAS_ATTRIBUTE(deprcated,4,0,0) || \ HEDLEY_ARM_VERSION_CHECK(4,1,0) # define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) # define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) #elif HEDLEY_MSVC_VERSION_CHECK(14,0,0) # define HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) # define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) #elif HEDLEY_MSVC_VERSION_CHECK(13,10,0) # define HEDLEY_DEPRECATED(since) _declspec(deprecated) # define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #else # define HEDLEY_DEPRECATED(since) # define HEDLEY_DEPRECATED_FOR(since, replacement) #endif 

I'll leave it as an exercise to figure out how to get rid of the *_VERSION_CHECK and *_HAS_ATTRIBUTE macros if you don't want to use Hedley (I wrote Hedley largely so I wouldn't have to think about that on a regular basis).

If you use GLib, you can use the G_DEPRECATED and G_DEPRECATED_FOR macros. They're not as robust as the ones from Hedley, but if you already use GLib there is nothing to add.

Comments

4

Dealing with portable projects it's almost inevitable that you at some point need a section of preprocessed alternatives for a range of platforms. #ifdef this #ifdef that and so on.

In such a section you could very well conditionally define a way to deprecate symbols. My preference is usually to define a "warning" macro since most toolchains support custom compiler warnings. Then you can go on with a specific warning macro for deprecation etc. For the platforms supporting dedicated deprecation methods you can use that instead of warnings.

Comments

1

For Intel Compiler v19.0, use this as __INTEL_COMPILER evaluates to 1900:

# if defined(__INTEL_COMPILER) # define DEPRECATED [[deprecated]] # endif 

Works for the following language levels:

  • C++17 Support (/Qstd=c++17)
  • C++14 Support (/Qstd=c++14)
  • C++11 Support (/Qstd=c++11)
  • C11 Support (/Qstd=c11)
  • C99 Support (/Qstd=c99)

The Intel Compiler has what appears a bug in that it does not support the [[deprecated]] attribute on certain language elements that all other compilers do. For an example, compile v6.0.0 of the (remarkly superb) {fmtlib/fmt} library on GitHub with Intel Compiler v19.0. It will break. Then see the fix in the GitHub commit.

1 Comment

This is incorrect; C++ attributes do not work in C mode on ICC. Example. __attribute__((deprecated)), OTOH, works in C and C++ going back to at least ICC 13.0, probably much further (Intel tends not to document this type of stuff so I can't be sure).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.