From b7780b5e5dfb0a90c52f2d5e9d85ae99f83265ab Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 4 May 2023 15:22:01 +0200 Subject: [PATCH] Long live QtPrivate::CompactStorage<> This is a generalization of QPrivateSlotObject's FunctionStorage. Changes from the old API: - uses a more neutral API (s/func/object/) - preserves cv-qualifiers and value categories - preserves constexpr'ness - adds a disambiguation tag (e.g. for use in a compressed_pair). The main feature is that it transparently uses the empty base-class optimization to stow away empty classes without allocating separate bytes for them. To be used for the public QSlotObject and QGenericRunnable, at least, so finally pulled the trigger and made it a separate component. Change-Id: I9a13bbdd1dcf64aaf5fc7b2d40a60050d61800b6 Reviewed-by: Thiago Macieira --- src/corelib/CMakeLists.txt | 1 + src/corelib/kernel/qobject_p.h | 28 ++-------- src/corelib/tools/qfunctionaltools_impl.h | 68 +++++++++++++++++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 src/corelib/tools/qfunctionaltools_impl.h diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index d229a9dbc0..8053ca728b 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -282,6 +282,7 @@ qt_internal_add_module(Core tools/qduplicatetracker_p.h tools/qflatmap_p.h tools/qfreelist.cpp tools/qfreelist_p.h + tools/qfunctionaltools_impl.h tools/qhashfunctions.h tools/qiterator.h tools/qline.cpp tools/qline.h diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index ef89786a4d..61a0fe9ebb 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -18,6 +18,7 @@ #include #include "QtCore/qcoreevent.h" +#include #include "QtCore/qlist.h" #include "QtCore/qobject.h" #include "QtCore/qpointer.h" @@ -255,28 +256,7 @@ namespace QtPrivate { inline const QObject *getQObject(const QObjectPrivate *d) { return d->q_func(); } template -struct FunctionStorageByValue -{ - Func f; - Func &func() noexcept { return f; } -}; - -template -struct FunctionStorageEmptyBaseClassOptimization : Func -{ - Func &func() noexcept { return *this; } - using Func::Func; -}; - -template -using FunctionStorage = typename std::conditional_t< - std::conjunction_v< - std::is_empty, - std::negation> - >, - FunctionStorageEmptyBaseClassOptimization, - FunctionStorageByValue - >; +using FunctionStorage = QtPrivate::CompactStorage; template inline void assertObjectType(QObjectPrivate *d) { @@ -296,11 +276,11 @@ class QPrivateSlotObject : public QSlotObjectBase, private FunctionStorage delete that; break; case Call: - FuncType::template call(that->func(), + FuncType::template call(that->object(), static_cast(QObjectPrivate::get(r)), a); break; case Compare: - *ret = *reinterpret_cast(a) == that->func(); + *ret = *reinterpret_cast(a) == that->object(); break; case NumOperations: ; } diff --git a/src/corelib/tools/qfunctionaltools_impl.h b/src/corelib/tools/qfunctionaltools_impl.h new file mode 100644 index 0000000000..1f03b978e8 --- /dev/null +++ b/src/corelib/tools/qfunctionaltools_impl.h @@ -0,0 +1,68 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#if 0 +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + +#ifndef QFUNCTIONALTOOLS_IMPL_H +#define QFUNCTIONALTOOLS_IMPL_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { + +namespace detail { + +#define FOR_EACH_CVREF(op) \ + op(&) \ + op(const &) \ + op(&&) \ + op(const &&) \ + /* end */ + + +template +struct StorageByValue +{ + Object o; +#define MAKE_GETTER(cvref) \ + constexpr Object cvref object() cvref noexcept \ + { return static_cast(o); } + FOR_EACH_CVREF(MAKE_GETTER) +#undef MAKE_GETTER +}; + +template +struct StorageEmptyBaseClassOptimization : Object +{ +#define MAKE_GETTER(cvref) \ + constexpr Object cvref object() cvref noexcept \ + { return static_cast(*this); } + FOR_EACH_CVREF(MAKE_GETTER) +#undef MAKE_GETTER +}; +} // namespace detail + +template +using CompactStorage = typename std::conditional_t< + std::conjunction_v< + std::is_empty, + std::negation> + >, + detail::StorageEmptyBaseClassOptimization, + detail::StorageByValue + >; + +} // namespace QtPrivate + +#undef FOR_EACH_CVREF + +QT_END_NAMESPACE + +#endif // QFUNCTIONALTOOLS_IMPL_H