diff options
Diffstat (limited to 'src/corelib/kernel/qobjectdefs.h')
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 467 |
1 files changed, 339 insertions, 128 deletions
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index d47c311c18..190901d5d1 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Copyright (C) 2019 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2019 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOBJECTDEFS_H #define QOBJECTDEFS_H @@ -47,6 +11,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qobjectdefs_impl.h> +#include <QtCore/qtcoreexports.h> #include <QtCore/qtmetamacros.h> QT_BEGIN_NAMESPACE @@ -72,28 +37,31 @@ class QString; Q_CORE_EXPORT const char *qFlagLocation(const char *method); #ifndef QT_NO_META_MACROS -#ifndef QT_NO_DEBUG -# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) -# ifndef QT_NO_KEYWORDS -# define METHOD(a) qFlagLocation("0"#a QLOCATION) +# define QMETHOD_CODE 0 // member type codes +# define QSLOT_CODE 1 +# define QSIGNAL_CODE 2 +# define QT_PREFIX_CODE(code, a) QT_STRINGIFY(code) #a +# define QT_STRINGIFY_METHOD(a) QT_PREFIX_CODE(QMETHOD_CODE, a) +# define QT_STRINGIFY_SLOT(a) QT_PREFIX_CODE(QSLOT_CODE, a) +# define QT_STRINGIFY_SIGNAL(a) QT_PREFIX_CODE(QSIGNAL_CODE, a) +# ifndef QT_NO_DEBUG +# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) +# ifndef QT_NO_KEYWORDS +# define METHOD(a) qFlagLocation(QT_STRINGIFY_METHOD(a) QLOCATION) +# endif +# define SLOT(a) qFlagLocation(QT_STRINGIFY_SLOT(a) QLOCATION) +# define SIGNAL(a) qFlagLocation(QT_STRINGIFY_SIGNAL(a) QLOCATION) +# else +# ifndef QT_NO_KEYWORDS +# define METHOD(a) QT_STRINGIFY_METHOD(a) +# endif +# define SLOT(a) QT_STRINGIFY_SLOT(a) +# define SIGNAL(a) QT_STRINGIFY_SIGNAL(a) # endif -# define SLOT(a) qFlagLocation("1"#a QLOCATION) -# define SIGNAL(a) qFlagLocation("2"#a QLOCATION) -#else -# ifndef QT_NO_KEYWORDS -# define METHOD(a) "0"#a -# endif -# define SLOT(a) "1"#a -# define SIGNAL(a) "2"#a -#endif - -#define QMETHOD_CODE 0 // member type codes -#define QSLOT_CODE 1 -#define QSIGNAL_CODE 2 #endif // QT_NO_META_MACROS -#define Q_ARG(type, data) QArgument<type >(#type, data) -#define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data) +#define Q_ARG(Type, data) QtPrivate::Invoke::argument<Type>(QT_STRINGIFY(Type), data) +#define Q_RETURN_ARG(Type, data) QtPrivate::Invoke::returnArgument<Type>(QT_STRINGIFY(Type), data) class QObject; class QMetaMethod; @@ -103,6 +71,7 @@ class QMetaClassInfo; namespace QtPrivate { class QMetaTypeInterface; +template<typename T> constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType(); } struct QMethodRawArguments @@ -110,6 +79,7 @@ struct QMethodRawArguments void **arguments; }; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) class Q_CORE_EXPORT QGenericArgument { public: @@ -157,6 +127,108 @@ public: : QGenericReturnArgument(aName, static_cast<void *>(&aData)) {} }; +#endif + +struct QMetaMethodArgument +{ + const QtPrivate::QMetaTypeInterface *metaType; + const char *name; + const void *data; +}; + +struct QMetaMethodReturnArgument +{ + const QtPrivate::QMetaTypeInterface *metaType; + const char *name; + void *data; +}; + +template <typename T> +struct QTemplatedMetaMethodReturnArgument : QMetaMethodReturnArgument +{ + using Type = T; +}; + +namespace QtPrivate { +namespace Invoke { +#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) +template <typename... Args> +using AreOldStyleArgs = std::disjunction<std::is_base_of<QGenericArgument, Args>...>; + +template <typename T, typename... Args> using IfNotOldStyleArgs = + std::enable_if_t<!AreOldStyleArgs<Args...>::value, T>; +#else +template <typename T, typename... Args> using IfNotOldStyleArgs = T; +#endif + +template <typename T> inline QMetaMethodArgument argument(const char *name, const T &t) +{ + if constexpr ((std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) || + !std::is_reference_v<T>) { + return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) }; + } else { + return { nullptr, name, std::addressof(t) }; + } +} + +template <typename T> +inline QTemplatedMetaMethodReturnArgument<T> returnArgument(const char *name, T &t) +{ + return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) }; +} + +template <typename T> inline const char *typenameHelper(const T &) +{ + return nullptr; +} +template <typename T> inline const void *dataHelper(const T &t) +{ + return std::addressof(t); +} +template <typename T> inline const QMetaTypeInterface *metaTypeHelper(const T &) +{ + return qMetaTypeInterfaceForType<T>(); +} + +inline const char *typenameHelper(QMetaMethodArgument a) +{ return a.name; } +inline const void *dataHelper(QMetaMethodArgument a) +{ return a.data; } +inline const QMetaTypeInterface *metaTypeHelper(QMetaMethodArgument a) +{ return a.metaType; } + +inline const char *typenameHelper(const char *) = delete; +template <typename T> inline const void *dataHelper(const char *) = delete; +inline const QMetaTypeInterface *metaTypeHelper(const char *) = delete; +inline const char *typenameHelper(const char16_t *) = delete; +template <typename T> inline const void *dataHelper(const char16_t *) = delete; +inline const QMetaTypeInterface *metaTypeHelper(const char16_t *) = delete; + +} // namespace QtPrivate::Invoke + +template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments) +{ + std::array params = { const_cast<const void *>(r.data), Invoke::dataHelper(arguments)... }; + std::array names = { r.name, Invoke::typenameHelper(arguments)... }; + std::array types = { r.metaType, Invoke::metaTypeHelper(arguments)... }; + static_assert(params.size() == types.size()); + static_assert(params.size() == names.size()); + + struct R { + decltype(params) parameters; + decltype(names) typeNames; + decltype(types) metaTypes; + constexpr qsizetype parameterCount() const { return qsizetype(parameters.size()); } + }; + return R { params, names, types }; +} +} // namespace QtPrivate + +template <typename T> void qReturnArg(const T &&) = delete; +template <typename T> inline QTemplatedMetaMethodReturnArgument<T> qReturnArg(T &data) +{ + return QtPrivate::Invoke::returnArgument(nullptr, data); +} struct Q_CORE_EXPORT QMetaObject { @@ -165,13 +237,16 @@ struct Q_CORE_EXPORT QMetaObject const QMetaObject *superClass() const; bool inherits(const QMetaObject *metaObject) const noexcept; - QObject *cast(QObject *obj) const; + QObject *cast(QObject *obj) const + { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); } const QObject *cast(const QObject *obj) const; -#if !defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) +#if !defined(QT_NO_TRANSLATION) || defined(Q_QDOC) QString tr(const char *s, const char *c, int n = -1) const; #endif // QT_NO_TRANSLATION + QMetaType metaType() const; + int methodOffset() const; int enumeratorOffset() const; int propertyOffset() const; @@ -188,6 +263,7 @@ struct Q_CORE_EXPORT QMetaObject int indexOfSignal(const char *signal) const; int indexOfSlot(const char *slot) const; int indexOfEnumerator(const char *name) const; + int indexOfProperty(const char *name) const; int indexOfClassInfo(const char *name) const; @@ -221,6 +297,7 @@ struct Q_CORE_EXPORT QMetaObject static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); +#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, @@ -254,7 +331,7 @@ struct Q_CORE_EXPORT QMetaObject static inline bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, - QGenericArgument val0 = QGenericArgument(nullptr), + QGenericArgument val0, QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), @@ -270,7 +347,7 @@ struct Q_CORE_EXPORT QMetaObject } static inline bool invokeMethod(QObject *obj, const char *member, - QGenericArgument val0 = QGenericArgument(nullptr), + QGenericArgument val0, QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), @@ -284,89 +361,162 @@ struct Q_CORE_EXPORT QMetaObject return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); } +#endif // Qt < 7.0 + + template <typename ReturnArg, typename... Args> static +#ifdef Q_QDOC + bool +#else + QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> +#endif + invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, + QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) + { + auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...); + return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(), + h.typeNames.data(), h.metaTypes.data()); + } + + template <typename... Args> static +#ifdef Q_QDOC + bool +#else + QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> +#endif + invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments) + { + QTemplatedMetaMethodReturnArgument<void> r = {}; + return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...); + } + + template <typename ReturnArg, typename... Args> static +#ifdef Q_QDOC + bool +#else + QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> +#endif + invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> r, + Args &&... arguments) + { + return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); + } + + template <typename... Args> static +#ifdef Q_QDOC + bool +#else + QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> +#endif + invokeMethod(QObject *obj, const char *member, Args &&... arguments) + { + QTemplatedMetaMethodReturnArgument<void> r = {}; + return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); + } -#ifdef Q_CLANG_QDOC +#ifdef Q_QDOC template<typename Functor, typename FunctorReturnType> - static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); + static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); template<typename Functor, typename FunctorReturnType> - static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret); + static bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret); + + template<typename Functor, typename FunctorReturnType, typename... Args> + static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments); + template<typename Functor, typename FunctorReturnType, typename... Args> + static bool invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments); + template<typename Functor, typename... Args> + static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments); + template<typename Functor, typename... Args> + static bool invokeMethod(QObject *context, Functor &&function, Args &&...arguments); #else - - // invokeMethod() for member function pointer template <typename Func> - static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && !std::is_convertible<Func, const char*>::value - && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type - invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, - Func function, - Qt::ConnectionType type = Qt::AutoConnection, - typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Func>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, Qt::ConnectionType type, + typename QtPrivate::Callable<Func>::ReturnType *ret) { - return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret); + using R = typename QtPrivate::Callable<Func>::ReturnType; + const auto getReturnArg = [ret]() -> QTemplatedMetaMethodReturnArgument<R> { + if constexpr (std::is_void_v<R>) + return {}; + else + return ret ? qReturnArg(*ret) : QTemplatedMetaMethodReturnArgument<R>{}; + }; + return invokeMethod(object, std::forward<Func>(function), type, getReturnArg()); } - template <typename Func> - static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && !std::is_convertible<Func, const char*>::value - && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type - invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, - Func function, - typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Func>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, typename QtPrivate::Callable<Func>::ReturnType *ret) { - return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret); + return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret); } - // invokeMethod() for function pointer (not member) - template <typename Func> - static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && !std::is_convertible<Func, const char*>::value - && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type - invokeMethod(QObject *context, Func function, - Qt::ConnectionType type = Qt::AutoConnection, - typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) + template <typename Func, typename... Args> + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Args...>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, Qt::ConnectionType type, + QTemplatedMetaMethodReturnArgument< + typename QtPrivate::Callable<Func, Args...>::ReturnType> + ret, + Args &&...args) { - return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret); + return invokeMethodCallableHelper(object, std::forward<Func>(function), type, ret, + std::forward<Args>(args)...); } - template <typename Func> - static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && !std::is_convertible<Func, const char*>::value - && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type - invokeMethod(QObject *context, Func function, - typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) + template <typename Func, typename... Args> + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Args...>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, Qt::ConnectionType type, Args &&...args) { - return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret); + using R = typename QtPrivate::Callable<Func, Args...>::ReturnType; + QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr, + nullptr }; + return invokeMethod(object, std::forward<Func>(function), type, r, + std::forward<Args>(args)...); } - // invokeMethod() for Functor - template <typename Func> - static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 - && !std::is_convertible<Func, const char*>::value, bool>::type - invokeMethod(QObject *context, Func function, - Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) + template <typename Func, typename... Args> + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Args...>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, + QTemplatedMetaMethodReturnArgument< + typename QtPrivate::Callable<Func, Args...>::ReturnType> + ret, + Args &&...args) { - return invokeMethodImpl(context, - new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), - type, - ret); + return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret, + std::forward<Args>(args)...); } - template <typename Func> - static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction - && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 - && !std::is_convertible<Func, const char*>::value, bool>::type - invokeMethod(QObject *context, Func function, decltype(function()) *ret) + template <typename Func, typename... Args> + static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, + QtPrivate::Invoke::AreOldStyleArgs<Args...>>, + bool> + invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, Args &&...args) { - return invokeMethodImpl(context, - new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), - Qt::AutoConnection, - ret); + using R = typename QtPrivate::Callable<Func, Args...>::ReturnType; + QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr, + nullptr }; + return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, r, + std::forward<Args>(args)...); } #endif - QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr), +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) + QObject *newInstance(QGenericArgument val0, QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), @@ -376,6 +526,20 @@ struct Q_CORE_EXPORT QMetaObject QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) const; +#endif + + template <typename... Args> +#ifdef Q_QDOC + QObject * +#else + QtPrivate::Invoke::IfNotOldStyleArgs<QObject *, Args...> +#endif + newInstance(Args &&... arguments) const + { + auto h = QtPrivate::invokeMethodHelper(QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...); + return newInstanceImpl(this, h.parameterCount(), h.parameters.data(), + h.typeNames.data(), h.metaTypes.data()); + } enum Call { InvokeMetaMethod, @@ -386,8 +550,9 @@ struct Q_CORE_EXPORT QMetaObject IndexOfMethod, RegisterPropertyMetaType, RegisterMethodArgumentMetaType, - RegisterQPropertyObserver, - SetQPropertyBinding + BindableProperty, + CustomCall, + ConstructInPlace, }; int static_metacall(Call, int, void **) const; @@ -399,6 +564,7 @@ struct Q_CORE_EXPORT QMetaObject } struct SuperData { + using Getter = const QMetaObject *(*)(); const QMetaObject *direct; SuperData() = default; constexpr SuperData(std::nullptr_t) : direct(nullptr) {} @@ -407,7 +573,6 @@ struct Q_CORE_EXPORT QMetaObject constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } #ifdef QT_NO_DATA_RELOCATION - using Getter = const QMetaObject *(*)(); Getter indirect = nullptr; constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} constexpr operator const QMetaObject *() const @@ -415,6 +580,7 @@ struct Q_CORE_EXPORT QMetaObject template <const QMetaObject &MO> static constexpr SuperData link() { return SuperData(QMetaObject::staticMetaObject<MO>); } #else + constexpr SuperData(Getter g) : direct(g()) {} constexpr operator const QMetaObject *() const { return direct; } template <const QMetaObject &MO> static constexpr SuperData link() @@ -429,13 +595,51 @@ struct Q_CORE_EXPORT QMetaObject typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; const SuperData *relatedMetaObjects; - QtPrivate::QMetaTypeInterface *const *metaTypes; + const QtPrivate::QMetaTypeInterface *const *metaTypes; void *extradata; //reserved for future use } d; private: + // Just need to have this here with a separate name so the other inline + // functions can call this without any ambiguity + template <typename Func, typename... Args> + static bool + invokeMethodCallableHelper(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, + Func &&function, Qt::ConnectionType type, const QMetaMethodReturnArgument &ret, + Args &&...args) + { + using Callable = QtPrivate::Callable<Func, Args...>; + using ExpectedArguments = typename Callable::Arguments; + static_assert(sizeof...(Args) <= ExpectedArguments::size, "Too many arguments"); + using ActualArguments = QtPrivate::List<Args...>; + static_assert(QtPrivate::CheckCompatibleArguments<ActualArguments, + ExpectedArguments>::value, + "Incompatible arguments"); + + auto h = QtPrivate::invokeMethodHelper(ret, std::forward<Args>(args)...); + + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + auto callable = new QtPrivate::QCallableObject<std::decay_t<Func>, ActualArguments, + typename Callable::ReturnType>(std::forward<Func>(function)); + return invokeMethodImpl(object, callable, type, h.parameterCount(), h.parameters.data(), + h.typeNames.data(), h.metaTypes.data()); + } + + static bool invokeMethodImpl(QObject *object, const char *member, Qt::ConnectionType type, + qsizetype parameterCount, const void *const *parameters, const char *const *names, + const QtPrivate::QMetaTypeInterface * const *metaTypes); + static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj, + Qt::ConnectionType type, qsizetype parameterCount, + const void *const *params, const char *const *names, + const QtPrivate::QMetaTypeInterface *const *metaTypes); +#if QT_CORE_REMOVED_SINCE(6, 7) static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); +#endif + static QObject *newInstanceImpl(const QMetaObject *mobj, qsizetype parameterCount, + const void **parameters, const char **typeNames, + const QtPrivate::QMetaTypeInterface **metaTypes); friend class QTimer; + friend class QChronoTimer; }; class Q_CORE_EXPORT QMetaObject::Connection { @@ -453,20 +657,27 @@ public: #ifdef Q_QDOC operator bool() const; #else + // still using the restricted bool trick here, in order to support + // code using copy-init (e.g. `bool ok = connect(...)`) typedef void *Connection::*RestrictedBool; operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } #endif - Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; } - Connection &operator=(Connection &&other) noexcept - { qSwap(d_ptr, other.d_ptr); return *this; } + Connection(Connection &&other) noexcept : d_ptr(std::exchange(other.d_ptr, nullptr)) {} + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) + void swap(Connection &other) noexcept { qt_ptr_swap(d_ptr, other.d_ptr); } }; +inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept +{ + lhs.swap(rhs); +} + inline const QMetaObject *QMetaObject::superClass() const { return d.superdata; } namespace QtPrivate { - /* Trait that tells is a the Object has a Q_OBJECT macro */ + // Trait that tells if a QObject has a Q_OBJECT macro template <typename Object> struct HasQ_OBJECT_Macro { template <typename T> static char test(int (T::*)(QMetaObject::Call, int, void **)); |