如何避免嵌套弃用函数调用的警告?

How to avoid warning from nested deprecated function call?

我支持一个 C++ 库,并希望将一些遗留函数声明为已弃用。不幸的是,这些函数相互调用,我从它们的编译中收到警告。例如:

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

我想避免关于从 bar() 主体编译中调用已弃用函数的警告,但如果某些外部函数(未标记为已弃用)调用 foo() 或 bar() 时仍然会出现该警告。有可能吗?

虽然这不适用于发布的 OP 情况,但由于 bar() 从库的 header 中调用 foo(),因此有一个适用于任何人的直接解决方案在没有特定限制的情况下面临同样的问题。所以它可能对登陆这里的其他人有用。

有效,您需要两组不同的 header。一种是图书馆的用户使用它,另一种是图书馆本身使用它。我们可以在这种情况下这样做,因为 [[deprecated]] 不应该对生成的代码产生任何影响。

您“可以”单独维护它们,但这显然非常脆弱。值得庆幸的是,该语言确实为我们提供了一种方法,可以在一个文件中包含相同 header 的两个“版本”:oft-maligned,并且公平地说 oft-misused,Macro.

作为奖励,如果 [[deprecated]] 恰好是强制用户使用 C++14 或更高版本的原因,您可以通过检查 [=15= 同时提供对旧版本标准的支持] 或适当的功能宏。

//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

使用 -DMY_LIB_NO_DEPRECATE 编译库,好像在该过程的特定阶段不存在弃用警告。用户仍然会收到所有弃用警告,除非他们通过同时定义 MY_LIB_NO_DEPRECATE.

明确选择退出这些警告

不要被这里使用的宏吓到。使用它们来区分相同 header 的 internal/external 版本是一种常见且行之有效的做法。 Windows 如果没有它,几乎不可能编写 dll。

在 OP 的情况下,如果可以将 bar() 的定义从 header 移动到库的实现中,那么它们也应该很好。

您可以忽略弃用警告。它在技术上不可移植,但 it works 在所有 4 个主要编译器上,至少:

#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

你可以在图书馆范围内这样做:

MY_LIB_IGNORE_DEPRECATED_BEGIN

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

MY_LIB_IGNORE_DEPRECATED_END

或者你可以只保护有问题的电话:

[[deprecated]] void foo();

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