简体   繁体   中英

How to avoid warning from nested deprecated function call?

I support a C++ library, and want to declare a number of legacy functions as deprecated. Unfortunately, these functions call one another, and I receive warnings from their compilation. For example:

[[deprecated]] void foo();
[[deprecated]] void bar() { foo(); }

I would like to avoid a warning about calling deprecated function from bar() body compilation, but still has that warning if some outside function (not marked as deprecated) calls foo() or bar(). Is it somehow possible?

While this does not work for OP's circumstance as posted, on account of bar() invoking foo() from within the library's header, there is a straightforward solution that is applicable to anyone facing the same issue without that specific constraint. So it could be useful to other people landing here.

Effectively , you want two different sets of headers. One when users of the library use it, and one when the library itself uses it. We can do this in this case because [[deprecated]] is not supposed to have any influence on the resulting generated code.

You "could" just maintain both of them separately, but that would obviously be very fragile. Thankfully, the language does provide us with a way to have two "versions" of the same header in one single file: The oft-maligned, and to be fair also oft-misused, Macro.

As a bonus, if [[deprecated]] happens to be what forces users to use C++14 or above, you can provide support for older versions of the standard at the same time by checking __cplusplus or the appropriate feature macro.

//mylib.h

#if !defined(MY_LIB_NO_DEPRECATE) && __has_cpp_attribute(deprecated)
  #define MY_LIB_DEPRECATED [[deprecated]]
#else
  #define MY_LIB_DEPRECATED
#endif

// ...

MY_LIB_DEPRECATED void foo();
MY_LIB_DEPRECATED void bar();

// ...

#undef MY_LIB_DEPRECATED

Compile the library with -DMY_LIB_NO_DEPRECATE , and it's like the deprecation warnings are not there for that specific phase of the process. Users will still get all the deprecation warnings, unless they explicitly opt out of them by also defining MY_LIB_NO_DEPRECATE .

Don't get spooked by the use of macros here. Using them to distinguish between internal/external versions of the same header is a common and well established practice. Windows dlls would be practically impossible to write without it.

In OP's case, if moving bar() 's definition from the header into the library's implementation is a possibility, then they should be good to go as well.

You can ignore the deprecation warnings. It's not technically portable, but it works on all 4 major compilers, at least:

#if defined(__GNUC__)

#define MY_LIB_IGNORE_DEPRECATED_BEGIN \
    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")

#define MY_LIB_IGNORE_DEPRECATED_END \
    _Pragma("GCC diagnostic pop")

#elif defined(_MSC_VER)

#define MY_LIB_IGNORE_DEPRECATED_BEGIN \
    _Pragma("warning(push)") \
    _Pragma("warning(disable : 4996)")

#define MY_LIB_IGNORE_DEPRECATED_END \
    _Pragma("warning(pop)")

#else

#define MY_LIB_IGNORE_DEPRECATED_BEGIN
#define MY_LIB_IGNORE_DEPRECATED_END

#endif

You can do it library-wide:

MY_LIB_IGNORE_DEPRECATED_BEGIN

[[deprecated]] void foo();
[[deprecated]] void bar() { foo(); }

MY_LIB_IGNORE_DEPRECATED_END

Or you can guard just the offending calls:

[[deprecated]] void foo();

[[deprecated]] void bar()
{
MY_LIB_IGNORE_DEPRECATED_BEGIN
    foo();
MY_LIB_IGNORE_DEPRECATED_END
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM