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>
bb10
Marc Mutz 2023-05-04 15:22:01 +02:00
parent 9f0b4e18cd
commit b7780b5e5d
3 changed files with 73 additions and 24 deletions

View File

@ -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

View File

@ -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: ;
}

View File

@ -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