summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-05-04 15:22:01 +0200
committerMarc Mutz <marc.mutz@qt.io>2023-05-09 22:54:05 +0200
commitb7780b5e5dfb0a90c52f2d5e9d85ae99f83265ab (patch)
tree27198cfa279770baf8d86c18662a58ed8e809af2
parent9f0b4e18cd6929eb161e9526b496f9bb8a6e1c78 (diff)
downloadqtbase-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.txt1
-rw-r--r--src/corelib/kernel/qobject_p.h28
-rw-r--r--src/corelib/tools/qfunctionaltools_impl.h68
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