如何在保留弃用警告的同时删除类

How to delete classes while keeping deprecation warnings

本文关键字:删除 警告 保留      更新时间:2023-10-16

我正在努力寻找一种好的方法,从我的库中删除不推荐使用的类,同时保留好的错误消息。这个想法是基于我已经做过的一些功能:

namespace
{
[[deprecated("This function has been replaced by combust()")]]
void explode() = delete; // Using variadic templates in reality to have all signatures covered
void combust() {}
}
int main()
{
explode();
combust();
}

在clang中,这给了我一个很好的错误消息:

<source>:11:2: error: call to deleted function 'explode': This function has been replaced by combust()
explode();
^~~~~~~

GCC只给我一个消息,这个函数已经被删除了。尽管如此,这仍然表明了每个试图升级库的人的意图,他们忽略了弃用警告。

所以,由于这是一个c++库,我主要有类,并且正在寻找正确的方法来对这些类进行类似的操作。我目前的方法是这样的:

namespace
{
class [[deprecated("Class has been replaced by Bar")]] Foo
{
Foo () = delete; // And every other method I had in this class
};
class Bar
{
};
}
int main()
{
Foo f;
Bar b;
}

这基本上给了我以下clang中的警告/错误(以及GCC中的类似警告/错误):

<source>:13:5: warning: 'Foo' is deprecated: Class has been replaced by Bar [-Wdeprecated-declarations]
Foo f;
^
<source>:3:60: note: 'Foo' has been explicitly marked deprecated here
class [[deprecated("Class has been replaced by Bar")]] Foo
^
<source>:13:9: error: call to deleted constructor of '(anonymous namespace)::Foo'
Foo f;
^
<source>:5:8: note: 'Foo' has been explicitly marked deleted here
Foo () = delete;
^

在我可以使用这些无用的函数代码的地方,因为这是一行代码,这对类来说会很麻烦,因为它们可能有很多方法。

因此,我正在寻找一种很好的方法来完成以下工作:(非编译代码)

class [[deprecated("Class has been replaced by Bar")]] Foo = delete;

我得到的一个oneliner是:

struct [[deprecated("Class has been replaced by Bar")]] Foo { Foo() = delete; };
struct [[deprecated("Class has been replaced by Bar")]] Foo;

请注意,这并不包括通过引用传递Foo和调用某些方法的情况。

有人有更好的解决方案来删除类,同时对以下某些版本发出明确的弃用警告吗?

使用static_assert可以做到这一点,因为它会导致带有消息的编译时错误。但是,如果放置在非模板化函数中,它将始终断言。为了应对这种情况,我们将其作为一个模板函数,断言依赖于参数。如果不使用函数,这不会导致错误,因为它不会被实例化。

template <int I = 0>
void explode()
{
static_assert(I && false, "This function has been replaced by combust()");
}
int main()
{
// error: static_assert failed: "This function has been replaced by combust()"
explode();
}

这也可以用于类。但是,由于需要模板参数,因此需要使用typedef。

namespace
{
template <int I = 0>
class FooDeprec
{
static_assert(I && false, "Class has been replaced by Bar");
FooDeprec() = default; // no need to delete
};
using Foo = FooDeprec<>;
}
int main()
{
// error: static_assert failed "Class has been replaced by Bar"
Foo f;
}

这样做的好处是不需要太多更改——您可以保留成员函数的声明。