C + + 标记为弃用

我在一个接口中有一个方法,我想用便携式 C + + 废弃它。 当我为此谷歌所有我得到的是一个微软特定的解决方案; #pragma deprecated__declspec(deprecated)

一个二等奖的解决方案将是 ifdef一个 MSVC 和一个海湾合作委员会的解决方案。

107663 次浏览

在 GCC 中,你可以像下面这样声明你的函数:

void myfunc() __attribute__ ((deprecated));

这将在. c 文件中使用该函数时触发编译时警告。

你可以在“诊断实用程序”下面找到更多的信息 Http://gcc.gnu.org/onlinedocs/gcc/pragmas.html

在处理可移植项目时,您几乎不可避免地需要一部分针对一系列平台的预处理备选方案。# 如果这个 # 如果那个等等。

在这样一个部分中,您可以很好地有条件地定义一种弃用符号的方法。我通常倾向于定义一个“警告”宏,因为大多数工具链都支持自定义编译器警告。然后,你可以继续使用一个特定的警告宏等。 对于支持专用弃用方法的平台,可以使用该方法而不是警告。

这应该会奏效:

#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);

但是,如果函数返回类型的名称中有一个逗号,例如 std::pair<int, int>,您将会遇到问题,因为这将被预处理器解释为向 DEPRECATED 宏传递2个参数。在这种情况下,您必须键入 def 返回类型。

编辑: 更简单(但可能不太兼容)的版本 给你

在 C + + 14中,可以使用 [[deprecated]]属性将函数标记为已弃用(参见7.6.5[ dcl.attr.depreated ])。

属性标记 deprecated可以用来标记仍然允许使用的名称和实体,但由于某些原因不鼓励使用。

例如,不推荐使用下列函数 foo:

[[deprecated]]
void foo(int);

可以提供一条消息,说明为什么不赞成使用该名称或实体:

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

消息必须是字符串文字。

有关详细信息,请参阅 “在 C + + 14中标记为已弃用”

下面是我的 2008年的答案的一个简化版本:

#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);

参见:

以下是2018年的一个更为完整的答案。

现在,许多工具不仅允许您将某些内容标记为已弃用,还允许您提供消息。这允许您告诉人们什么时候某些东西被弃用了,并且可能指引他们找到一个替代品。

编译器的支持仍然有很多种:

  • C + + 14支持 [[deprecated]]/[[deprecated(message)]]
  • __attribute__((deprecated))支持 GCC 4.0 + 和 ARM 4.1 +
  • 支持 __attribute__((deprecated))__attribute__((deprecated(message)))的内容包括:
    • 海湾合作委员会4.5 +
    • 几个伪装成 GCC 4.5 + 的编译器(通过设置 __GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__)
    • Intel C/C + + Compiler 至少可以追溯到16(你不能信任 __GNUC__/__GNUC_MINOR__,他们只是把它设置为安装了 GCC 的任何版本)
    • ARM 5.6 +
  • MSVC 从13.10开始就支持 __declspec(deprecated)(Visual Studio 2003)
  • MSVC 从14.0开始就支持 __declspec(deprecated(message))(Visual Studio 2005)

您还可以在 C + + 11中的最新版本的 clang 中使用 [[gnu::deprecated]],基于 __has_cpp_attribute(gnu::deprecated)

我在 海德利中使用了一些宏来自动处理所有这些内容,并且不断更新,但是当前版本(v2)看起来像这样:

#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

如果你不想使用 Hedley,我会把它作为一个练习来解决如何摆脱 *_VERSION_CHECK*_HAS_ATTRIBUTE宏的问题(我大部分时间都在写 Hedley,所以我不需要经常考虑这个问题)。

如果使用 GLib,则可以使用 G_DEPRECATEDG_DEPRECATED_FOR宏。它们没有赫德利的那么健壮,但是如果你已经使用了 GLib,就没有什么可补充的了。

对于 Intel Compiler v19.0,当 __INTEL_COMPILER的计算结果为 1900时使用以下命令:

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

适用于以下语言水平:

  • C + + 17支持(/Qstd = c + + 17)
  • C + + 14支持(/Qstd = c + + 14)
  • C + + 11支持(/Qstd = c + + 11)
  • C11支持(/Qstd = C11)
  • C99支持(/Qstd = C99)

Intel 编译器似乎有一个 bug,它不支持其他所有编译器都支持的某些语言元素上的 [[deprecated]]属性。例如,使用 Intel Compiler v19.0在 GitHub 上编译(非常棒的) { fmtlib/fmt }库的 v6.0.0。会断的。然后看看 修复 GitHub 提交