diff options
Diffstat (limited to 'src/corelib/kernel/qobjectdefs.h')
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 200 |
1 files changed, 131 insertions, 69 deletions
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 6aa2d46782..190901d5d1 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -11,6 +11,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qobjectdefs_impl.h> +#include <QtCore/qtcoreexports.h> #include <QtCore/qtmetamacros.h> QT_BEGIN_NAMESPACE @@ -142,12 +143,18 @@ struct QMetaMethodReturnArgument 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> struct AreOldStyleArgs : - std::disjunction<std::is_base_of<QGenericArgument, Args>...> -{}; +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 @@ -164,7 +171,8 @@ template <typename T> inline QMetaMethodArgument argument(const char *name, cons } } -template <typename T> inline QMetaMethodReturnArgument returnArgument(const char *name, T &t) +template <typename T> +inline QTemplatedMetaMethodReturnArgument<T> returnArgument(const char *name, T &t) { return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) }; } @@ -216,8 +224,8 @@ template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgu } } // namespace QtPrivate -template <typename T> inline QMetaMethodReturnArgument qReturnArg(T &&) = delete; -template <typename T> inline QMetaMethodReturnArgument qReturnArg(T &data) +template <typename T> void qReturnArg(const T &&) = delete; +template <typename T> inline QTemplatedMetaMethodReturnArgument<T> qReturnArg(T &data) { return QtPrivate::Invoke::returnArgument(nullptr, data); } @@ -255,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; @@ -354,14 +363,14 @@ struct Q_CORE_EXPORT QMetaObject } #endif // Qt < 7.0 - template <typename... Args> static + 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, - QMetaMethodReturnArgument r, Args &&... arguments) + QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) { auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...); return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(), @@ -376,17 +385,17 @@ struct Q_CORE_EXPORT QMetaObject #endif invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments) { - QMetaMethodReturnArgument r = {}; + QTemplatedMetaMethodReturnArgument<void> r = {}; return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...); } - template <typename... Args> static + template <typename ReturnArg, typename... Args> static #ifdef Q_QDOC bool #else QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> #endif - invokeMethod(QObject *obj, const char *member, QMetaMethodReturnArgument r, + invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) { return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); @@ -400,87 +409,108 @@ struct Q_CORE_EXPORT QMetaObject #endif invokeMethod(QObject *obj, const char *member, Args &&... arguments) { - QMetaMethodReturnArgument r = {}; + QTemplatedMetaMethodReturnArgument<void> r = {}; return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); } #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 @@ -570,14 +600,46 @@ struct Q_CORE_EXPORT QMetaObject } 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 { @@ -615,7 +677,7 @@ 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 **)); |