如何将C++类方法标记为deprecated?

dced5bon  于 2023-02-20  发布在  其他
关注(0)|答案(7)|浏览(188)

我有一个在C++接口中的方法,我想弃用它,它有可移植的代码。
当我在谷歌上搜索这个的时候,我得到的只是一个微软特有的解决方案;#pragma deprecated__declspec(deprecated)
如果没有通用的或完全可移植的弃用解决方案,我将接受一个"二等奖解决方案",它可以用于多个特定的编译器,如MSVC和GCC。

h22fl7wq

h22fl7wq1#

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

  • attribute-token* deprecated可用于标记仍然允许使用但由于某种原因不鼓励使用的名称和实体。

例如,不建议使用以下函数foo

[[deprecated]]
void foo(int);

可以提供一条消息,说明名称或实体被弃用的原因:

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

消息必须是字符串文本。
有关详细信息,请参见“Marking as deprecated in C++14”

zpgglvta

zpgglvta2#

这应该可以达到目的:

#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个参数。在这种情况下,您必须typedef返回类型。
编辑:here版本更简单(但兼容性可能不那么广泛)。

lmyy7pcs

lmyy7pcs3#

下面是我的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);

另见:

qrjkbowd

qrjkbowd4#

在GCC中,你可以用deprecated属性声明你的函数,如下所示:

void myfunc() __attribute__ ((deprecated));

在.c文件中使用该函数时,这将触发编译时警告。
您可以在http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html的“诊断杂注”下找到更多信息

gudnpqoy

gudnpqoy5#

下面是2018年的一个更完整的答案。
如今,许多工具不仅允许你标记某个东西为弃用,而且还提供一条消息,这样你就可以告诉人们什么时候某个东西被弃用了,也许还可以指引他们去寻找替代品。
编译器支持仍然有很多变化:

  • C++14语言支持[[deprecated]]/[[deprecated(message)]]
  • GCC 4.0及以上版本和ARM 4.1及以上版本支持__attribute__((deprecated))
  • __attribute__((deprecated))__attribute__((deprecated(message)))支持用于:
  • GCC 4.5以上
  • 几个伪装成GCC 4.5+的编译器(通过设置__GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__
  • “英特尔C/C++编译器”至少返回到16(您不能信任__GNUC__/__GNUC_MINOR__,他们只是将其设置为安装的GCC版本)
  • 手臂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)
我在Hedley中有一些宏来自动处理所有这些,我一直在更新这些宏,但当前版本(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

如果您不想使用赫德利,我将把它作为一个练习来讨论如何去除*_VERSION_CHECK*_HAS_ATTRIBUTE宏(我编写Hedley主要是为了不需要经常考虑这个问题)。
如果你使用GLib,你可以使用G_DEPRECATEDG_DEPRECATED_FOR宏,它们没有赫德利的宏健壮,但是如果你已经使用GLib,没有什么需要添加的。

ecfsfe2w

ecfsfe2w6#

在处理可移植项目时,几乎不可避免的是,您在某个时候需要一部分针对一系列平台的预处理替代方案。#ifdef this #ifdef that等等。
在这样的一节中,你可以很好地有条件地定义一种反对符号的方式。我的偏好通常是定义一个“警告”宏,因为大多数工具链支持自定义编译器警告。然后你可以继续使用一个特定的反对警告宏等。对于支持专用反对方法的平台,你可以使用它来代替警告。

raogr8fs

raogr8fs7#

对于“英特尔编译器19.0版”,当__INTEL_COMPILER计算为1900时,使用此公式:

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

适用于以下语言级别:

  • C17语言支持(/Qstd=c17)
  • C14语言支持(/Qstd=c14)
  • C11语言支持(/Qstd=c11)
  • C11支持(/Qstd=c11)
  • C99支持(/Qstd=c99)

“英特尔编译器”似乎有一个错误,它不支持某些语言元素上的[[deprecated]]属性,而其它所有编译器都支持。例如,使用“英特尔编译器”19.0版在GitHub上编译{fmtlib/fmt}库的6.0.0版(非常出色)。它会中断。然后查看fix in the GitHub commit

相关问题