C++ mark as deprecated

C++

C++ Problem Overview


I have a method in an interface that I want to deprecate with portable C++. When I Googled for this all I got was a Microsoft specific solution; #pragma deprecated and __declspec(deprecated).

A second prize solution would be to ifdef a MSVC and a GCC solution.

C++ Solutions


Solution 1 - C++

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”.

Solution 2 - C++

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.

Solution 3 - C++

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:

Solution 4 - C++

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

Solution 5 - C++

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.

Solution 6 - C++

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.

Solution 7 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDiederikView Question on Stackoverflow
Solution 1 - C++Joseph MansfieldView Answer on Stackoverflow
Solution 2 - C++Michael PlatingsView Answer on Stackoverflow
Solution 3 - C++Michael PlatingsView Answer on Stackoverflow
Solution 4 - C++Terje MikalView Answer on Stackoverflow
Solution 5 - C++nemequView Answer on Stackoverflow
Solution 6 - C++sharkinView Answer on Stackoverflow
Solution 7 - C++ContangoView Answer on Stackoverflow