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

How do I temporarily disable warnings for usage of [[deprecated]] variables?

本文关键字:变量 警告 何暂时      更新时间:2023-10-16

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

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

struct MyObject
{
int foo;
[[deprecated("Use foo instead")]]
int bar;
void do_setup()
{
foo = 1;
// For backward compatibility only
#pragma warning(suppress : 4996)
bar = 2;
}
};

我不喜欢这个解决方案的部分是它依赖于非标准的、工具链定义的pragma指令。我可能还会陷入一些#ifdef地狱,因为我也支持 Clang。

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

没有标准驱动的方式来禁用使用特定代码块中已弃用名称的警告,因为标准本身仅建议实现可能想要如何对deprecated做出反应,而该建议只是"如果程序引用名称则发出警告"。

一种简单的替代方法是重命名原始名称,并让已弃用的填充程序引用它:

struct MyObject
{
int foo;
int bar_; // renamed from bar
[[deprecated("Use foo instead")]]
int& bar = bar_;
void do_setup()
{
foo = 1;
// For backward compatibility only
bar_ = 2;
}
};

当然,这更适合已弃用的函数,因为填充函数基本上是免费的。在这里,您在每个MyObject中占用了引用的空间,并且您需要非常小心复制/移动/分配的内容。(请注意,const MyObject仍将具有非常量bar。或者,您可以将bar_变成一个成员函数,返回对bar的引用(以及该引用的 const 版本(,以获得类似的效果。

如果你想将一个自由函数/全局变量标记为已弃用,你会有更大的灵活性,因为deprecated属性可以放在re声明上。检查一下:

int deprecatedFunc()
{
return 3;
}
int grandfathered()
{
return deprecatedFunc();
}
[[deprecated("NO")]]
int deprecatedFunc();
int warnme()
{
return deprecatedFunc();
}

所以你可以有一个没有deprecated的"内部"头,并有一个面向用户的头,其中包括内部头,然后用deprecated重新声明。可悲的是,你不能走另一条路:一旦一个名称被声明为deprecated一次,你就不能通过以后的重新声明来取消弃用它。

你可以从编译器中隐藏它:

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-deprecated-declarations完成