diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-11-30 10:13:09 +0100 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-12-14 20:49:47 +0100 |
commit | f894f04c9d03878116de61c11d4591da67c10378 (patch) | |
tree | d3d8d69f68cc6d439250260475f7af950d1bcf17 /src/corelib/kernel | |
parent | a337b8360f149313f5bf37dc5867413d846a3a97 (diff) |
QObject: remove the operator comma hack
It was the easiest way to implement this back in the day without an
explosion of combinatorics.
Change-Id: Ia930b1a2ed1e465a826ffffd179c5bb4657d0562
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qobjectdefs_impl.h | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index ec9f12f5f1..1e953f29b6 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -51,25 +51,27 @@ namespace QtPrivate { template <typename L> struct List_Left<L, 0> { typedef List<> Value; }; /* - Trick to set the return value of a slot that works even if the signal or the slot returns void - to be used like - function(), ApplyReturnValue<ReturnType>(&return_value) - if function() returns a value, the operator,(T, ApplyReturnValue<ReturnType>) is called, but if it - returns void, the built-in one is used without an error. - */ - template <typename T> - struct ApplyReturnValue { - void *data; - explicit ApplyReturnValue(void *data_) : data(data_) {} + This is used to store the return value from a slot, whether the caller + wants to store this value (QMetaObject::invokeMethod() with + qReturnArg() or non-void signal ) or not. + */ + struct FunctorCallBase + { + template <typename R, typename Lambda> + static void call_internal(void **args, Lambda &&fn) noexcept(noexcept(fn())) + { + using SlotRet = decltype(fn()); + if constexpr (std::is_void_v<R> || std::is_void_v<SlotRet>) { + Q_UNUSED(args); + } else { + if (args[0]) { + *reinterpret_cast<R *>(args[0]) = fn(); + return; + } + } + fn(); + } }; - template<typename T, typename U> - void operator,(T &&value, const ApplyReturnValue<U> &container) { - if (container.data) - *reinterpret_cast<U *>(container.data) = std::forward<T>(value); - } - template<typename T> - void operator,(T, const ApplyReturnValue<void> &) {} - /* The FunctionPointer<Func> struct is a type trait for function pointer. @@ -132,41 +134,57 @@ namespace QtPrivate { template <typename, typename, typename, typename> struct FunctorCall; template <int... II, typename... SignalArgs, typename R, typename Function> - struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> { - static void call(Function &f, void **arg) { - f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> : FunctorCallBase + { + static void call(Function &f, void **arg) + { + call_internal<R>(arg, [&] { + return f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...); + }); } }; template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> - struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> { + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> : FunctorCallBase + { static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) { assertObjectType<Obj>(o); - (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + call_internal<R>(arg, [&] { + return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...); + }); } }; template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> - struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> { + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> : FunctorCallBase + { static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg) { assertObjectType<Obj>(o); - (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + call_internal<R>(arg, [&] { + return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...); + }); } }; template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> - struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> { + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> : FunctorCallBase + { static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg) { assertObjectType<Obj>(o); - (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + call_internal<R>(arg, [&]() noexcept { + return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...); + }); } }; template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj> - struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> { + struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> : FunctorCallBase + { static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg) { assertObjectType<Obj>(o); - (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); + call_internal<R>(arg, [&]() noexcept { + return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...); + }); } }; |