QtGlobal: introduce a helper macro for declaring the RO5 SMFs as defaulted

If a class honors the RO0 we usually just leave a comment in the class'
body, and don't explicitly redeclare any of the RO5 special member
functions.

In some cases we may need to redeclare (some of) them. The main use-case
so far is to declare a protected destructor for a base class that is
not polymorphic, in order to prevent slicing; the compiler-provided
destructor is always public.

We can easily declare and default such a protected destructor, but that
comes with the problem that now we're violating the RO5 (as far as C++
is concerned, declaring a SMF counts towards the RO5, even if it's
immediately defaulted).

Specifically: by declaring the destructor, the class loses the
compiler-generated move operations, and the copy operations are
generated but deprecated. Clang >= 18 warns about this.

In such a scenario we *must* redeclare all five SMFs... and default them
all. This is boilerplate, therefore I'm adding a macro to streamline it.

Apply the new macro to a couple of cases were manual refactoring has
already been done.

Pick-to: 6.8 6.5
Change-Id: I5dc0ff9770621fbec0b1057c164d0623f901e3e9
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit fcb57391f73d36914e10ba964dbd9b01fe6f3af2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2025-02-04 15:19:31 +01:00 committed by Qt Cherry-pick Bot
parent 40dc33a9d3
commit 711b86fa24
3 changed files with 28 additions and 15 deletions

View File

@ -83,6 +83,31 @@ QT_BEGIN_NAMESPACE
return *this; \
}
/*
This macro defines the RO5 special member functions (destructor,
copy+move constructors and assignment operators) as defaulted.
Normally we don't use this macro if we're fine with these functions
to be public; we instead leave a comment in the class declaration,
something like:
// compiler-generated special member functions are fine!
In some cases a class may need to redeclare these functions, for
instance if it wants to change their accessibility. Since
defaulting all five is boilerplate, use this macro instead.
Note that the default constructor is not covered, and this macro
will prevented its automatic generation.
*/
#define QT_DECLARE_RO5_SMF_AS_DEFAULTED(Class) \
~Class() = default; \
Class(const Class &) = default; \
Class(Class &&) = default; \
Class &operator=(const Class &) = default; \
Class &operator=(Class &&) = default;
/*
These macros can be used to define tag structs in the preferred way (ie.
with explicit default ctor).

View File

@ -72,11 +72,7 @@ template <bool noex, class Const, class R, class... ArgTypes>
class function_ref_base
{
protected:
~function_ref_base() = default;
function_ref_base(const function_ref_base &) = default;
function_ref_base(function_ref_base &&) = default;
function_ref_base &operator=(const function_ref_base &) = default;
function_ref_base &operator=(function_ref_base &&) = default;
QT_DECLARE_RO5_SMF_AS_DEFAULTED(function_ref_base)
using BoundEntityType = detail::BoundEntityType<Const>;

View File

@ -32,11 +32,7 @@ template <typename T> struct QListSpecialMethodsBase
{
protected:
QListSpecialMethodsBase() = default;
~QListSpecialMethodsBase() = default;
QListSpecialMethodsBase(const QListSpecialMethodsBase &) = default;
QListSpecialMethodsBase(QListSpecialMethodsBase &&) = default;
QListSpecialMethodsBase &operator=(const QListSpecialMethodsBase &) = default;
QListSpecialMethodsBase &operator=(QListSpecialMethodsBase &&) = default;
QT_DECLARE_RO5_SMF_AS_DEFAULTED(QListSpecialMethodsBase)
using Self = QList<T>;
Self *self() { return static_cast<Self *>(this); }
@ -58,11 +54,7 @@ template <typename T> struct QListSpecialMethods : QListSpecialMethodsBase<T>
{
protected:
QListSpecialMethods() = default;
~QListSpecialMethods() = default;
QListSpecialMethods(const QListSpecialMethods &) = default;
QListSpecialMethods(QListSpecialMethods &&) = default;
QListSpecialMethods &operator=(const QListSpecialMethods &) = default;
QListSpecialMethods &operator=(QListSpecialMethods &&) = default;
QT_DECLARE_RO5_SMF_AS_DEFAULTED(QListSpecialMethods)
public:
using QListSpecialMethodsBase<T>::indexOf;