【问题标题】:C++ mark as deprecatedC++ 标记为已弃用
【发布时间】:2010-09-22 15:32:00
【问题描述】:

我想在可移植 C++ 中弃用的接口中有一个方法。 当我用谷歌搜索时,我得到的只是微软特定的解决方案; #pragma deprecated__declspec(deprecated)

二等奖解决方案是ifdef MSVC 和 GCC 解决方案。

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    void myfunc() __attribute__ ((deprecated));
    

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        这应该可以解决问题:

        #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

        【讨论】:

        • 而不是#error,最好是#define DEPRECATED(func) func
        • mxp:弃用只是一个警告,因此我会说它不受支持的警告就是您所需要的。
        • 是的,我会选择“#warning You need to implement DEPRECATED for this compiler”之类的。如果这是不可能的,那么搬运工可以#define DEPRECATED(FUNC) FUNC,并且没有它。
        • 不幸的是,没有标准的方法可以在 C++ 中输出编译警告:P #pragma 消息必须这样做。
        • gcc 的属性语法现在允许属性与__declspec(deprecated) 位于相同的位置,因此可以简化宏。
        【解决方案4】:

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

        【讨论】:

        • 你能在宏中使用 [[deprecated]] 吗?
        • @Zammbi 您应该可以,因为宏在编译前由预处理器处理。 [[deprecated]] 应该出现在宏被评估的地方(并让编译器输出相关的警告)。
        • 那么 C++11 怎么样?
        【解决方案5】:

        这是我的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(...));
        • 您应该编辑 2008 年的答案,而不是发布新答案。
        • 这可能不像我的其他答案那样广泛兼容,因此我单独添加了这个。
        【解决方案6】:

        这是 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)
          • ARM 5.6+
        • MSVC 从 13.10 (Visual Studio 2003) 开始支持 __declspec(deprecated)
        • MSVC 自 14.0 (Visual Studio 2005) 起支持 __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_DEPRECATEDG_DEPRECATED_FOR 宏。它们不如 Hedley 的强大,但如果您已经使用 GLib,则无需添加任何内容。

        【讨论】:

          【解决方案7】:

          对于 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)

          英特尔编译器似乎存在一个错误,即它不支持所有其他编译器所支持的某些语言元素的[[deprecated]] 属性。例如,使用 Intel Compiler v19.0 在 GitHub 上编译(非常出色){fmtlib/fmt} 库的 v6.0.0。它会破裂。然后查看fix in the GitHub commit

          【讨论】:

          • 这是不正确的; C++ 属性在 ICC 上的 C 模式下不起作用。 Example__attribute__((deprecated)),OTOH,在 C 和 C++ 中工作,至少可以追溯到 ICC 13.0,可能更远(英特尔倾向于不记录这类东西,所以我不能确定)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-22
          相关资源
          最近更新 更多