summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-11-30 10:13:09 +0100
committerThiago Macieira <thiago.macieira@intel.com>2023-12-14 20:49:47 +0100
commitf894f04c9d03878116de61c11d4591da67c10378 (patch)
treed3d8d69f68cc6d439250260475f7af950d1bcf17 /src/corelib/kernel
parenta337b8360f149313f5bf37dc5867413d846a3a97 (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.h76
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]))...);
+ });
}
};