C++ 如何临时禁用使用[[已弃用]]变量的警告?

C++ 如何临时禁用使用[[已弃用]]变量的警告?,c++,c++17,C++,C++17,我在变量上使用C++的[[deprecated]]属性。有些实现代码仍然使用此变量来支持向后兼容性。我不希望该代码发出编译器警告。但是,如果有人引入使用该不推荐变量的新代码,我确实希望发出警告 是否有一种与编译器无关的方法来禁用使用[[deprecated]]变量的警告?如果不是,我是否必须这样做(以MSVC为例): struct MyObject { int foo; [[已弃用(“改用foo”)]] int-bar; void do_setup() { foo=1; //仅用于向后兼容 #杂

我在变量上使用C++的
[[deprecated]]
属性。有些实现代码仍然使用此变量来支持向后兼容性。我不希望该代码发出编译器警告。但是,如果有人引入使用该不推荐变量的新代码,我确实希望发出警告

是否有一种与编译器无关的方法来禁用使用
[[deprecated]]
变量的警告?如果不是,我是否必须这样做(以MSVC为例):

struct MyObject
{
int foo;
[[已弃用(“改用foo”)]]
int-bar;
void do_setup()
{
foo=1;
//仅用于向后兼容
#杂注警告(抑制:4996)
bar=2;
}
};
我不喜欢这个解决方案的一部分是它依赖于非标准的、工具链定义的
pragma
指令。因为我也支持Clang,所以我可能会进入一些
#ifdef
地狱


使用C++17,对于标记为
[[deprecated]]]
的实体的使用,最推荐的抑制工具链警告/诊断的方法是什么?对于上下文:这一点很重要,因为我将警告视为我使用的所有工具链上的错误。

没有标准驱动的方法来禁用使用特定代码块中已弃用名称的警告,因为标准本身仅建议实现可能要如何对已弃用的
作出反应,这个建议只是“如果程序引用名称,则发出警告”

一种简单的替代方法是重命名原始名称,并使用不推荐使用的垫片引用该名称:

struct MyObject
{
int foo;
int bar_;//从bar重命名
[[已弃用(“改用foo”)]]
int&bar=bar;
void do_setup()
{
foo=1;
//仅用于向后兼容
巴=2;
}
};
当然,这更适合不推荐使用的函数,因为填充函数基本上是免费的。在这里,您占用了每个
MyObject
中的引用空间,您需要非常小心地处理您的复制/移动/分配内容。(请注意,
const MyObject
仍将具有非const
bar
)或者,您可以将
bar
设置为成员函数,返回对
bar
的引用(以及该对象的const版本),以获得类似效果

如果您想将自由函数/全局变量标记为不推荐使用,那么您就有了更大的灵活性,因为
deprecated
属性可以重新声明。检查它:

int deprecatedFunc()
{
    return 3;
}

int grandfathered()
{
    return deprecatedFunc();
}

[[deprecated("NO")]]
int deprecatedFunc();

int warnme()
{
    return deprecatedFunc();
}

因此,您可以有一个没有
弃用的
的“内部”标题,并有一个面向用户的标题,其中包括内部标题,然后使用
弃用的
重新声明。不幸的是,你不能走另一条路:一旦一个名字被声明为不推荐的
一次,你就不能用以后的重新声明来取消它的不推荐。

你可以对编译器隐藏它:

struct MyObject
{
    int foo;

    [[deprecated("Use foo instead")]]
    int bar;

    void do_setup()
    {
        foo = 1;

        // Fooled you compiler!
        _bar() = 2;
    }

private:
    auto _bar() noexcept -> int&;
    auto _bar() const noexcept -> int const&;
};
然后,在另一个文件中:

auto MyObject::_bar() noexcept -> int& {
    return bar;
}

auto MyObject::_bar() const noexcept -> int const& {
    return bar;
}

然后,可以在禁用所有警告的情况下编译此文件。在GCC和Clang中,它是通过
-Wno不推荐的声明来完成的

我看不到任何忽略警告的标准方法。@Jarod42
suppress
仅在下一行自动执行此操作。该标准甚至不要求首先显示诊断消息,因此它没有办法停止它。您处于实现定义的行为领域,您需要决定要涵盖哪些实现。我不认为“不推荐”是“向后兼容特性”的好工具。某事物被弃用是因为有删除它的意图。向后兼容功能是一种功能,因此用户应该期望得到支持。我理解想要阻止新代码使用某些东西的愿望,但是想想看:什么能阻止新代码仅仅使用任何不推荐的旁路呢?要么用户应该停止使用它,要么他们应该期望它得到支持;这里没有中间立场。@NicolBolas在本例中的向后兼容性是为了与另一个软件组件的旧版本进行互操作。我不赞成它们,因为最终的目的是代码将被删除。它不能保证留在那里。它还表明我不希望修改/改进代码。基本上,不要在这上面浪费时间。一旦所有旧版本都消失了,代码就可以安全地删除。肯定有一个中间立场。我不认为“向后兼容性”的定义像你描述的那样严格。