如何标记 C++ 类方法已被弃用?

发布于 2024-07-08 19:50:29 字数 413 浏览 7 评论 0原文

我想用可移植代码弃用 C++ 接口中的一个方法。

当我用谷歌搜索这个问题时,我得到的只是微软特定的解决方案; #pragma 已弃用__declspec(已弃用)

如果通用或完全可移植的弃用解决方案不可用,我将接受可用于多个特定编译器(例如 MSVC 和 GCC)的“二等奖解决方案”。

I have a method in a C++ interface that I want to deprecate, with portable code.

When I Googled for this all I got was a Microsoft specific solution; #pragma deprecated and __declspec(deprecated).

If a general or fully-portable deprecation solution is not available, I will accept as a "second prize solution" one that can be used multiple specific compilers, like MSVC and a GCC.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

画离情绘悲伤 2024-07-15 19:50:29

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

属性令牌 已弃用可用于标记仍允许使用但由于某种原因不鼓励使用的名称和实体。

例如,以下函数 foo 已被弃用:

[[deprecated]]
void foo(int);

可以提供一条消息来描述名称或实体为何被弃用:

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

该消息必须是字符串文字。

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

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

九公里浅绿 2024-07-15 19:50:29

这应该可以解决问题:

#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 ,您将会遇到问题,因为这将被预处理器解释为传递DEPRECATED 宏的 2 个参数。 在这种情况下,您必须 typedef 返回类型。

编辑:更简单(但可能不太广泛兼容)版本此处

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.

我的影子我的梦 2024-07-15 19:50:29

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

另请参阅:

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:

总以为 2024-07-15 19:50:29

在 GCC 中,您可以使用已弃用的属性来声明函数,如下所示:

void myfunc() __attribute__ ((deprecated));

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

您可以在“诊断编译指示”下找到更多信息:
http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html

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

无法回应 2024-07-15 19:50:29

这是 2018 年更完整的答案。

如今,很多工具不仅可以让您将某些内容标记为已弃用,还可以提供一条消息。 这使您可以告诉人们某些内容何时被弃用,并可能引导他们寻找替代品。

编译器支持仍然有很多变化:

  • C++14 支持 [[deprecated]]/[[deprecated(message)]]
  • GCC 4.0+ 和 ARM 4.1+ 支持
  • __attribute__((deprecated)) __attribute__((deprecated))__attribute__((deprecated(message)))< /code> 支持:
    • GCC 4.5+
    • 几个伪装成 GCC 4.5+ 的编译器(通过设置 __GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__
    • 英特尔 C/C++ 编译器至少可追溯到 16(您不能信任 __GNUC__/__GNUC_MINOR__,他们只是将其设置为安装的 GCC 版本)
    • ARM 5.6+

  • MSVC 支持 __declspec(deprecated) 自 13.10 (Visual Studio 2003) 起
  • MSVC 自 14.0 (Visual Studio 2005) 起支持 __declspec(deprecated(message))

您还可以使用 [[gnu::已弃用]] 在 C++11 的最新版本的 clang 中,基于 __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(我主要写了 Hedley,这样我就不必定期考虑这个问题)。

如果您使用 GLib,则可以使用 G_DEPRECATEDG_DEPRECATED_FOR 宏。 它们不像 Hedley 的那样强大,但如果您已经使用 GLib,则无需添加任何内容。

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.

撩人痒 2024-07-15 19:50:29

处理可移植项目时,您几乎不可避免地在某些时候需要一系列平台的预处理替代方案。 #ifdef 这个 #ifdef 那等等。

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

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.

御弟哥哥 2024-07-15 19:50:29

对于英特尔编译器 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)

英特尔编译器出现如下内容一个错误是它不支持所有其他编译器都支持的某些语言元素上的 [[deprecated]] 属性。 例如,编译 GitHub 上的(非常出色的){fmtlib/fmt} 库的 v6.0.0使用英特尔编译器 v19.0。 它会破裂。 然后查看 GitHub 提交中的修复

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文