【发布时间】:2010-09-22 15:32:00
【问题描述】:
我想在可移植 C++ 中弃用的接口中有一个方法。
当我用谷歌搜索时,我得到的只是微软特定的解决方案; #pragma deprecated 和 __declspec(deprecated)。
二等奖解决方案是ifdef MSVC 和 GCC 解决方案。
【问题讨论】:
标签: c++
我想在可移植 C++ 中弃用的接口中有一个方法。
当我用谷歌搜索时,我得到的只是微软特定的解决方案; #pragma deprecated 和 __declspec(deprecated)。
二等奖解决方案是ifdef MSVC 和 GCC 解决方案。
【问题讨论】:
标签: c++
在 GCC 中,您可以使用已弃用的属性声明您的函数,如下所示:
void myfunc() __attribute__ ((deprecated));
当在 .c 文件中使用该函数时,这将触发编译时警告。
您可以在“诊断编译指示”下找到更多信息,网址为 http://gcc.gnu.org/onlinedocs/gcc/Pragmas.html
【讨论】:
在处理可移植项目时,您几乎不可避免地会在某些时候需要针对一系列平台进行预处理的替代方案。 #ifdef 这个 #ifdef 那等等。
在这样的部分中,您可以很好地有条件地定义一种弃用符号的方法。我的偏好通常是定义一个“警告”宏,因为大多数工具链都支持自定义编译器警告。然后,您可以继续使用特定的警告宏进行弃用等。 对于支持专用弃用方法的平台,您可以使用它而不是警告。
【讨论】:
这应该可以解决问题:
#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> 因为这将被预处理器解释为将 2 个参数传递给 DEPRECATED 宏。在这种情况下,您必须 typedef 返回类型。
编辑:更简单(但可能不太兼容)版本here。
【讨论】:
__declspec(deprecated) 位于相同的位置,因此可以简化宏。
在 C++14 中,您可以使用 [[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”。
【讨论】:
这是我的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);
另见:
【讨论】:
[[deprecate]] 您已弃用的宏? :-)
DEPRECATED void foo(...); 而不是 DEPRECATED(void foo(...));
这是 2018 年更完整的答案。
如今,许多工具不仅可以让您将某些内容标记为已弃用,还可以提供消息。这使您可以告诉人们何时弃用了某些东西,并可能将他们指向替代品。
编译器支持的种类还是很多的:
[[deprecated]]/[[deprecated(message)]]。__attribute__((deprecated))
__attribute__((deprecated)) 和 __attribute__((deprecated(message))) 支持:
__GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__)__GNUC__/__GNUC_MINOR__,他们只是将它设置为安装的任何版本的 GCC)__declspec(deprecated)
__declspec(deprecated(message))
您还可以在 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
如果你不想使用 Hedley,我将把它作为一个练习来弄清楚如何摆脱 *_VERSION_CHECK 和 *_HAS_ATTRIBUTE 宏(我主要写了 Hedley,所以我不必思考定期讨论)。
如果您使用 GLib,则可以使用 G_DEPRECATED 和 G_DEPRECATED_FOR 宏。它们不如 Hedley 的强大,但如果您已经使用 GLib,则无需添加任何内容。
【讨论】:
对于 Intel Compiler v19.0,将其用作 __INTEL_COMPILER 的计算结果为 1900:
# if defined(__INTEL_COMPILER)
# define DEPRECATED [[deprecated]]
# endif
适用于以下语言级别:
英特尔编译器似乎存在一个错误,即它不支持所有其他编译器所支持的某些语言元素的[[deprecated]] 属性。例如,使用 Intel Compiler v19.0 在 GitHub 上编译(非常出色){fmtlib/fmt} 库的 v6.0.0。它会破裂。然后查看fix in the GitHub commit。
【讨论】:
__attribute__((deprecated)),OTOH,在 C 和 C++ 中工作,至少可以追溯到 ICC 13.0,可能更远(英特尔倾向于不记录这类东西,所以我不能确定)。