SonarCloud seems to have recently started triggering S4963 (“Remove this class’ destructor so that the class follows the rule of Zero.”) on destructor declarations as well as definitions. I think this is a bad idea, because it ends up causing issues with forward declaration. Consider:
// foo.hpp
#include <memory>
class Bar; // forward declaration
class Foo
{
public:
~Foo(); // S4963 triggered here
private:
std::unique_ptr<Bar> m_bar;
};
At this point the destructor cannot be generated, since destructing the unique_ptr needs to access Bar’s destructor, which isn’t available at this point since Bar is an incomplete type. Once Bar’s definition is known (perhaps through a #include directive in the corresponding .cpp file), the destructor can later (perhaps in a separate file, e.g. foo.cpp) be defined as Foo::~Foo() = default, which I don’t really consider to be a rule-of-zero violation.
There are a few valid reasons for doing this: perhaps Bar also depends on Foo, or perhaps including the definition of Bar results in a lot of additional heavy dependencies which needlessly slow down compilation of clients of Foo that do not need to care that it is implemented in terms of Bar. I therefore think destructor declarations should be ignored when triggering S4963, and only triggering the rule if the definition is non-defaulted.