diff options
author | Marc Mutz <marc.mutz@qt.io> | 2023-05-04 15:22:01 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-05-09 22:54:05 +0200 |
commit | b7780b5e5dfb0a90c52f2d5e9d85ae99f83265ab (patch) | |
tree | 27198cfa279770baf8d86c18662a58ed8e809af2 | |
parent | 9f0b4e18cd6929eb161e9526b496f9bb8a6e1c78 (diff) | |
download | qtbase-b7780b5e5dfb0a90c52f2d5e9d85ae99f83265ab.tar.gz |
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 <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 28 | ||||
-rw-r--r-- | src/corelib/tools/qfunctionaltools_impl.h | 68 |
3 files changed, 73 insertions, 24 deletions
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 <QtCore/private/qglobal_p.h> #include "QtCore/qcoreevent.h" +#include <QtCore/qfunctionaltools_impl.h> #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 <typename Func> -struct FunctionStorageByValue -{ - Func f; - Func &func() noexcept { return f; } -}; - -template <typename Func> -struct FunctionStorageEmptyBaseClassOptimization : Func -{ - Func &func() noexcept { return *this; } - using Func::Func; -}; - -template <typename Func> -using FunctionStorage = typename std::conditional_t< - std::conjunction_v< - std::is_empty<Func>, - std::negation<std::is_final<Func>> - >, - FunctionStorageEmptyBaseClassOptimization<Func>, - FunctionStorageByValue<Func> - >; +using FunctionStorage = QtPrivate::CompactStorage<Func>; template <typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d) { @@ -296,11 +276,11 @@ class QPrivateSlotObject : public QSlotObjectBase, private FunctionStorage<Func> delete that; break; case Call: - FuncType::template call<Args, R>(that->func(), + FuncType::template call<Args, R>(that->object(), static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a); break; case Compare: - *ret = *reinterpret_cast<Func *>(a) == that->func(); + *ret = *reinterpret_cast<Func *>(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 <QtCore/qtconfigmacros.h> + +#include <type_traits> + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { + +namespace detail { + +#define FOR_EACH_CVREF(op) \ + op(&) \ + op(const &) \ + op(&&) \ + op(const &&) \ + /* end */ + + +template <typename Object, typename = void> +struct StorageByValue +{ + Object o; +#define MAKE_GETTER(cvref) \ + constexpr Object cvref object() cvref noexcept \ + { return static_cast<Object cvref>(o); } + FOR_EACH_CVREF(MAKE_GETTER) +#undef MAKE_GETTER +}; + +template <typename Object, typename = void> +struct StorageEmptyBaseClassOptimization : Object +{ +#define MAKE_GETTER(cvref) \ + constexpr Object cvref object() cvref noexcept \ + { return static_cast<Object cvref>(*this); } + FOR_EACH_CVREF(MAKE_GETTER) +#undef MAKE_GETTER +}; +} // namespace detail + +template <typename Object, typename Tag = void> +using CompactStorage = typename std::conditional_t< + std::conjunction_v< + std::is_empty<Object>, + std::negation<std::is_final<Object>> + >, + detail::StorageEmptyBaseClassOptimization<Object, Tag>, + detail::StorageByValue<Object, Tag> + >; + +} // namespace QtPrivate + +#undef FOR_EACH_CVREF + +QT_END_NAMESPACE + +#endif // QFUNCTIONALTOOLS_IMPL_H |