File indexing completed on 2026-08-17 09:17:29
0001
0002
0003
0004
0005
0006 #ifndef QOBJECTDEFS_H
0007 #error Do not include qobjectdefs_impl.h directly
0008 #include <QtCore/qnamespace.h>
0009 #endif
0010
0011 #if 0
0012 #pragma qt_sync_skip_header_check
0013 #pragma qt_sync_stop_processing
0014 #endif
0015
0016 #include <QtCore/qfunctionaltools_impl.h>
0017
0018 #include <memory>
0019
0020 QT_BEGIN_NAMESPACE
0021 class QObject;
0022 class QObjectPrivate;
0023 class QMetaMethod;
0024 class QByteArray;
0025
0026 namespace QtPrivate {
0027 template <typename T> struct RemoveRef { typedef T Type; };
0028 template <typename T> struct RemoveRef<T&> { typedef T Type; };
0029 template <typename T> struct RemoveConstRef { typedef T Type; };
0030 template <typename T> struct RemoveConstRef<const T&> { typedef T Type; };
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <typename... Ts> struct List { static constexpr size_t size = sizeof...(Ts); };
0040 template<typename T> struct SizeOfList { static constexpr size_t value = 1; };
0041 template<> struct SizeOfList<List<>> { static constexpr size_t value = 0; };
0042 template<typename ...Ts> struct SizeOfList<List<Ts...>> { static constexpr size_t value = List<Ts...>::size; };
0043 template <typename Head, typename... Tail> struct List<Head, Tail...> {
0044 static constexpr size_t size = 1 + sizeof...(Tail);
0045 typedef Head Car; typedef List<Tail...> Cdr;
0046 };
0047 template <typename, typename> struct List_Append;
0048 template <typename... L1, typename...L2> struct List_Append<List<L1...>, List<L2...>> { typedef List<L1..., L2...> Value; };
0049 template <typename L, int N> struct List_Left {
0050 typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
0051 };
0052 template <typename L> struct List_Left<L, 0> { typedef List<> Value; };
0053
0054
0055
0056
0057
0058
0059 struct FunctorCallBase
0060 {
0061 template <typename R, typename Lambda>
0062 static void call_internal([[maybe_unused]] void **args, Lambda &&fn)
0063 noexcept(std::is_nothrow_invocable_v<Lambda>)
0064 {
0065 if constexpr (std::is_void_v<R> || std::is_void_v<std::invoke_result_t<Lambda>>) {
0066 std::forward<Lambda>(fn)();
0067 } else {
0068 if (args[0])
0069 *reinterpret_cast<R *>(args[0]) = std::forward<Lambda>(fn)();
0070 else
0071 [[maybe_unused]] auto r = std::forward<Lambda>(fn)();
0072 }
0073 }
0074 };
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
0093
0094 template<typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d);
0095 template<typename Obj> inline void assertObjectType(QObject *o)
0096 {
0097
0098 [[maybe_unused]] auto staticcast = [](QObject *obj) { return static_cast<Obj *>(obj); };
0099 [[maybe_unused]] auto qobjcast = [](QObject *obj) { return Obj::staticMetaObject.cast(obj); };
0100 #ifdef __cpp_rtti
0101 [[maybe_unused]] auto dyncast = [](QObject *obj) { return dynamic_cast<Obj *>(obj); };
0102 auto cast = dyncast;
0103 #else
0104 auto cast = qobjcast;
0105 #endif
0106 Q_ASSERT_X(cast(o), Obj::staticMetaObject.className(),
0107 "Called object is not of the correct type (class destructor may have already run)");
0108 }
0109
0110 template <typename, typename, typename, typename> struct FunctorCall;
0111 template <size_t... II, typename... SignalArgs, typename R, typename Function>
0112 struct FunctorCall<std::index_sequence<II...>, List<SignalArgs...>, R, Function> : FunctorCallBase
0113 {
0114 static void call(Function &f, void **arg)
0115 {
0116 call_internal<R>(arg, [&] {
0117 return f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
0118 });
0119 }
0120 };
0121 template <size_t... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
0122 struct FunctorCall<std::index_sequence<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> : FunctorCallBase
0123 {
0124 static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg)
0125 {
0126 assertObjectType<Obj>(o);
0127 call_internal<R>(arg, [&] {
0128 return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
0129 });
0130 }
0131 };
0132 template <size_t... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
0133 struct FunctorCall<std::index_sequence<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> : FunctorCallBase
0134 {
0135 static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg)
0136 {
0137 assertObjectType<Obj>(o);
0138 call_internal<R>(arg, [&] {
0139 return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
0140 });
0141 }
0142 };
0143 template <size_t... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
0144 struct FunctorCall<std::index_sequence<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) noexcept> : FunctorCallBase
0145 {
0146 static void call(SlotRet (Obj::*f)(SlotArgs...) noexcept, Obj *o, void **arg)
0147 {
0148 assertObjectType<Obj>(o);
0149 call_internal<R>(arg, [&]() noexcept {
0150 return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
0151 });
0152 }
0153 };
0154 template <size_t... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
0155 struct FunctorCall<std::index_sequence<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const noexcept> : FunctorCallBase
0156 {
0157 static void call(SlotRet (Obj::*f)(SlotArgs...) const noexcept, Obj *o, void **arg)
0158 {
0159 assertObjectType<Obj>(o);
0160 call_internal<R>(arg, [&]() noexcept {
0161 return (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...);
0162 });
0163 }
0164 };
0165
0166 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)>
0167 {
0168 typedef Obj Object;
0169 typedef List<Args...> Arguments;
0170 typedef Ret ReturnType;
0171 typedef Ret (Obj::*Function) (Args...);
0172 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
0173 template <typename SignalArgs, typename R>
0174 static void call(Function f, Obj *o, void **arg) {
0175 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, o, arg);
0176 }
0177 };
0178 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const>
0179 {
0180 typedef Obj Object;
0181 typedef List<Args...> Arguments;
0182 typedef Ret ReturnType;
0183 typedef Ret (Obj::*Function) (Args...) const;
0184 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
0185 template <typename SignalArgs, typename R>
0186 static void call(Function f, Obj *o, void **arg) {
0187 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, o, arg);
0188 }
0189 };
0190
0191 template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...)>
0192 {
0193 typedef List<Args...> Arguments;
0194 typedef Ret ReturnType;
0195 typedef Ret (*Function) (Args...);
0196 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false};
0197 template <typename SignalArgs, typename R>
0198 static void call(Function f, void *, void **arg) {
0199 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, arg);
0200 }
0201 };
0202
0203 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) noexcept>
0204 {
0205 typedef Obj Object;
0206 typedef List<Args...> Arguments;
0207 typedef Ret ReturnType;
0208 typedef Ret (Obj::*Function) (Args...) noexcept;
0209 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
0210 template <typename SignalArgs, typename R>
0211 static void call(Function f, Obj *o, void **arg) {
0212 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, o, arg);
0213 }
0214 };
0215 template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const noexcept>
0216 {
0217 typedef Obj Object;
0218 typedef List<Args...> Arguments;
0219 typedef Ret ReturnType;
0220 typedef Ret (Obj::*Function) (Args...) const noexcept;
0221 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
0222 template <typename SignalArgs, typename R>
0223 static void call(Function f, Obj *o, void **arg) {
0224 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, o, arg);
0225 }
0226 };
0227
0228 template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...) noexcept>
0229 {
0230 typedef List<Args...> Arguments;
0231 typedef Ret ReturnType;
0232 typedef Ret (*Function) (Args...) noexcept;
0233 enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false};
0234 template <typename SignalArgs, typename R>
0235 static void call(Function f, void *, void **arg) {
0236 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Function>::call(f, arg);
0237 }
0238 };
0239
0240
0241
0242 template <typename T>
0243 struct NarrowingDetector { T t[1]; };
0244
0245 template <typename From, typename To, typename Enable = void>
0246 struct IsConvertibleWithoutNarrowing : std::false_type {};
0247
0248 template <typename From, typename To>
0249 struct IsConvertibleWithoutNarrowing<From, To,
0250 std::void_t< decltype( NarrowingDetector<To>{ {std::declval<From>()} } ) >
0251 > : std::true_type {};
0252
0253
0254
0255
0256
0257 template <typename From, typename To, typename Enable = void>
0258 struct AreArgumentsConvertibleWithoutNarrowingBase : std::false_type {};
0259
0260 template <typename From, typename To>
0261 struct AreArgumentsConvertibleWithoutNarrowingBase<From, To,
0262 std::enable_if_t<
0263 std::disjunction_v<std::is_same<From, To>, IsConvertibleWithoutNarrowing<From, To>>
0264 >
0265 > : std::true_type {};
0266
0267
0268
0269
0270
0271
0272 template<typename A1, typename A2> struct AreArgumentsCompatible {
0273 static int test(const std::remove_reference_t<A2>&);
0274 static char test(...);
0275 enum { value = sizeof(test(std::declval<std::remove_reference_t<A1>>())) == sizeof(int) };
0276 #ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
0277 using AreArgumentsConvertibleWithoutNarrowing = AreArgumentsConvertibleWithoutNarrowingBase<std::decay_t<A1>, std::decay_t<A2>>;
0278 static_assert(AreArgumentsConvertibleWithoutNarrowing::value, "Signal and slot arguments are not compatible (narrowing)");
0279 #endif
0280 };
0281 template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; };
0282 template<typename A> struct AreArgumentsCompatible<A&, A&> { enum { value = true }; };
0283
0284 template<typename A> struct AreArgumentsCompatible<void, A> { enum { value = true }; };
0285 template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; };
0286 template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; };
0287
0288 template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; };
0289 template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; };
0290 template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; };
0291 template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2>
0292 struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>>
0293 {
0294 enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value
0295 && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value };
0296 };
0297
0298
0299
0300
0301
0302
0303 template <typename Functor, typename ArgList> struct ComputeFunctorArgumentCount;
0304
0305 template <typename Functor, typename ArgList, bool Done> struct ComputeFunctorArgumentCountHelper
0306 { enum { Value = -1 }; };
0307 template <typename Functor, typename First, typename... ArgList>
0308 struct ComputeFunctorArgumentCountHelper<Functor, List<First, ArgList...>, false>
0309 : ComputeFunctorArgumentCount<Functor,
0310 typename List_Left<List<First, ArgList...>, sizeof...(ArgList)>::Value> {};
0311
0312 template <typename Functor, typename... ArgList> struct ComputeFunctorArgumentCount<Functor, List<ArgList...>>
0313 {
0314 template <typename F> static auto test(F f) -> decltype(((f.operator()((std::declval<ArgList>())...)), int()));
0315 static char test(...);
0316 enum {
0317 Ok = sizeof(test(std::declval<Functor>())) == sizeof(int),
0318 Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
0319 };
0320 };
0321
0322
0323 template <typename Functor, typename ArgList> struct FunctorReturnType;
0324 template <typename Functor, typename... ArgList> struct FunctorReturnType<Functor, List<ArgList...>>
0325 : std::invoke_result<Functor, ArgList...>
0326 { };
0327
0328 template<typename Func, typename... Args>
0329 struct FunctorCallable
0330 {
0331 using ReturnType = std::invoke_result_t<Func, Args...>;
0332 using Function = ReturnType(*)(Args...);
0333 enum {ArgumentCount = sizeof...(Args)};
0334 using Arguments = QtPrivate::List<Args...>;
0335
0336 template <typename SignalArgs, typename R>
0337 static void call(Func &f, void *, void **arg) {
0338 FunctorCall<std::index_sequence_for<Args...>, SignalArgs, R, Func>::call(f, arg);
0339 }
0340 };
0341
0342 template <typename Functor, typename... Args>
0343 struct HasCallOperatorAcceptingArgs
0344 {
0345 private:
0346 template <typename F, typename = void>
0347 struct Test : std::false_type
0348 {
0349 };
0350
0351 template <typename F>
0352 struct Test<F, std::void_t<decltype(std::declval<F>().operator()(std::declval<Args>()...))>>
0353 : std::true_type
0354 {
0355 };
0356
0357 public:
0358 using Type = Test<Functor>;
0359 static constexpr bool value = Type::value;
0360 };
0361
0362 template <typename Functor, typename... Args>
0363 constexpr bool
0364 HasCallOperatorAcceptingArgs_v = HasCallOperatorAcceptingArgs<Functor, Args...>::value;
0365
0366 template <typename Func, typename... Args>
0367 struct CallableHelper
0368 {
0369 private:
0370
0371
0372 static auto Resolve(std::true_type CallOperator) -> FunctorCallable<Func, Args...>;
0373 static auto Resolve(std::false_type CallOperator) -> FunctionPointer<std::decay_t<Func>>;
0374
0375 public:
0376 using Type = decltype(Resolve(typename HasCallOperatorAcceptingArgs<std::decay_t<Func>,
0377 Args...>::Type{}));
0378 };
0379
0380 template<typename Func, typename... Args>
0381 struct Callable : CallableHelper<Func, Args...>::Type
0382 {};
0383 template<typename Func, typename... Args>
0384 struct Callable<Func, List<Args...>> : CallableHelper<Func, Args...>::Type
0385 {};
0386
0387
0388
0389
0390
0391
0392 template<typename Prototype, typename Functor>
0393 inline constexpr std::enable_if_t<!std::disjunction_v<std::is_convertible<Prototype, const char *>,
0394 std::is_same<std::decay_t<Prototype>, QMetaMethod>,
0395 std::is_convertible<Functor, const char *>,
0396 std::is_same<std::decay_t<Functor>, QMetaMethod>
0397 >,
0398 int>
0399 countMatchingArguments()
0400 {
0401 using ExpectedArguments = typename QtPrivate::FunctionPointer<Prototype>::Arguments;
0402 using Actual = std::decay_t<Functor>;
0403
0404 if constexpr (QtPrivate::FunctionPointer<Actual>::IsPointerToMemberFunction
0405 || QtPrivate::FunctionPointer<Actual>::ArgumentCount >= 0) {
0406
0407 using ActualArguments = typename QtPrivate::FunctionPointer<Actual>::Arguments;
0408 if constexpr (QtPrivate::CheckCompatibleArguments<ExpectedArguments, ActualArguments>::value)
0409 return QtPrivate::FunctionPointer<Actual>::ArgumentCount;
0410 else
0411 return -1;
0412 } else {
0413
0414 return QtPrivate::ComputeFunctorArgumentCount<Actual, ExpectedArguments>::Value;
0415 }
0416 }
0417
0418
0419 class QSlotObjectBase
0420 {
0421
0422
0423
0424
0425 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0426 QAtomicInt m_ref = 1;
0427 typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret);
0428 const ImplFn m_impl;
0429 #else
0430 using ImplFn = void (*)(QSlotObjectBase* this_, QObject *receiver, void **args, int which, bool *ret);
0431 const ImplFn m_impl;
0432 QAtomicInt m_ref = 1;
0433 #endif
0434 protected:
0435
0436
0437 enum Operation {
0438 Destroy,
0439 Call,
0440 Compare,
0441
0442 NumOperations
0443 };
0444 public:
0445 explicit QSlotObjectBase(ImplFn fn) : m_impl(fn) {}
0446
0447
0448
0449 struct Deleter {
0450 void operator()(QSlotObjectBase *p) const noexcept
0451 { if (p) p->destroyIfLastRef(); }
0452
0453 static void cleanup(QSlotObjectBase *p) noexcept { Deleter{}(p); }
0454 };
0455
0456 bool ref() noexcept { return m_ref.ref(); }
0457 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0458 inline void destroyIfLastRef() noexcept
0459 { if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); }
0460
0461 inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; }
0462 inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, nullptr); }
0463 #else
0464 inline void destroyIfLastRef() noexcept
0465 { if (!m_ref.deref()) m_impl(this, nullptr, nullptr, Destroy, nullptr); }
0466
0467 inline bool compare(void **a)
0468 {
0469 bool ret = false;
0470 m_impl(this, nullptr, a, Compare, &ret);
0471 return ret;
0472 }
0473 inline void call(QObject *r, void **a) { m_impl(this, r, a, Call, nullptr); }
0474 #endif
0475 bool isImpl(ImplFn f) const { return m_impl == f; }
0476 protected:
0477 ~QSlotObjectBase() {}
0478 private:
0479 Q_DISABLE_COPY_MOVE(QSlotObjectBase)
0480 };
0481
0482 using SlotObjUniquePtr = std::unique_ptr<QSlotObjectBase,
0483 QSlotObjectBase::Deleter>;
0484 inline SlotObjUniquePtr copy(const SlotObjUniquePtr &other) noexcept
0485 {
0486 if (other)
0487 other->ref();
0488 return SlotObjUniquePtr{other.get()};
0489 }
0490
0491 class SlotObjSharedPtr {
0492 SlotObjUniquePtr obj;
0493 public:
0494 Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr() noexcept = default;
0495 Q_NODISCARD_CTOR Q_IMPLICIT SlotObjSharedPtr(std::nullptr_t) noexcept : SlotObjSharedPtr() {}
0496 Q_NODISCARD_CTOR explicit SlotObjSharedPtr(SlotObjUniquePtr o)
0497 : obj(std::move(o))
0498 {
0499
0500
0501 }
0502 Q_NODISCARD_CTOR SlotObjSharedPtr(const SlotObjSharedPtr &other) noexcept
0503 : obj{copy(other.obj)} {}
0504 SlotObjSharedPtr &operator=(const SlotObjSharedPtr &other) noexcept
0505 { auto copy = other; swap(copy); return *this; }
0506
0507 Q_NODISCARD_CTOR SlotObjSharedPtr(SlotObjSharedPtr &&other) noexcept = default;
0508 SlotObjSharedPtr &operator=(SlotObjSharedPtr &&other) noexcept = default;
0509 ~SlotObjSharedPtr() = default;
0510
0511 void swap(SlotObjSharedPtr &other) noexcept { obj.swap(other.obj); }
0512
0513 auto get() const noexcept { return obj.get(); }
0514 auto operator->() const noexcept { return get(); }
0515
0516 explicit operator bool() const noexcept { return bool(obj); }
0517 };
0518
0519
0520
0521
0522 template <typename Func, typename Args, typename R>
0523 class QCallableObject : public QSlotObjectBase,
0524 private QtPrivate::CompactStorage<std::decay_t<Func>>
0525 {
0526 using FunctorValue = std::decay_t<Func>;
0527 using Storage = QtPrivate::CompactStorage<FunctorValue>;
0528 using FuncType = Callable<Func, Args>;
0529
0530 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0531 Q_DECL_HIDDEN static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
0532 #else
0533
0534
0535
0536 Q_DECL_HIDDEN static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret)
0537 #endif
0538 {
0539 const auto that = static_cast<QCallableObject*>(this_);
0540 switch (which) {
0541 case Destroy:
0542 delete that;
0543 break;
0544 case Call:
0545 if constexpr (std::is_member_function_pointer_v<FunctorValue>)
0546 FuncType::template call<Args, R>(that->object(), static_cast<typename FuncType::Object *>(r), a);
0547 else
0548 FuncType::template call<Args, R>(that->object(), r, a);
0549 break;
0550 case Compare:
0551 if constexpr (std::is_member_function_pointer_v<FunctorValue>) {
0552 *ret = *reinterpret_cast<FunctorValue *>(a) == that->object();
0553 break;
0554 }
0555
0556 Q_FALLTHROUGH();
0557 case NumOperations:
0558 Q_UNUSED(ret);
0559 }
0560 }
0561 public:
0562 explicit QCallableObject(Func &&f) : QSlotObjectBase(&impl), Storage{std::move(f)} {}
0563 explicit QCallableObject(const Func &f) : QSlotObjectBase(&impl), Storage{f} {}
0564 };
0565
0566
0567
0568
0569
0570
0571 template <typename Func, typename = void>
0572 struct ContextTypeForFunctor {};
0573
0574 template <typename Func>
0575 struct ContextTypeForFunctor<Func,
0576 std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
0577 std::is_member_function_pointer<Func>
0578 >
0579 >
0580 >
0581 {
0582 using ContextType = QObject;
0583 };
0584 template <typename Func>
0585 struct ContextTypeForFunctor<Func,
0586 std::enable_if_t<std::conjunction_v<std::negation<std::is_convertible<Func, const char *>>,
0587 std::is_member_function_pointer<Func>,
0588 std::is_convertible<typename QtPrivate::FunctionPointer<Func>::Object *, QObject *>
0589 >
0590 >
0591 >
0592 {
0593 using ContextType = typename QtPrivate::FunctionPointer<Func>::Object;
0594 };
0595
0596
0597
0598
0599
0600
0601
0602 template <typename Prototype, typename Functor>
0603 static constexpr std::enable_if_t<QtPrivate::countMatchingArguments<Prototype, Functor>() >= 0,
0604 QtPrivate::QSlotObjectBase *>
0605 makeCallableObject(Functor &&func)
0606 {
0607 using ExpectedSignature = QtPrivate::FunctionPointer<Prototype>;
0608 using ExpectedReturnType = typename ExpectedSignature::ReturnType;
0609 using ExpectedArguments = typename ExpectedSignature::Arguments;
0610
0611 using ActualSignature = QtPrivate::FunctionPointer<Functor>;
0612 constexpr int MatchingArgumentCount = QtPrivate::countMatchingArguments<Prototype, Functor>();
0613 using ActualArguments = typename QtPrivate::List_Left<ExpectedArguments, MatchingArgumentCount>::Value;
0614
0615 static_assert(int(ActualSignature::ArgumentCount) <= int(ExpectedSignature::ArgumentCount),
0616 "Functor requires more arguments than what can be provided.");
0617
0618
0619 return new QtPrivate::QCallableObject<std::decay_t<Functor>, ActualArguments, ExpectedReturnType>(std::forward<Functor>(func));
0620 }
0621
0622 template<typename Prototype, typename Functor, typename = void>
0623 struct AreFunctionsCompatible : std::false_type {};
0624 template<typename Prototype, typename Functor>
0625 struct AreFunctionsCompatible<Prototype, Functor, std::enable_if_t<
0626 std::is_same_v<decltype(QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(std::declval<Functor>()))),
0627 QtPrivate::QSlotObjectBase *>>
0628 > : std::true_type {};
0629
0630 template<typename Prototype, typename Functor>
0631 inline constexpr bool AssertCompatibleFunctions() {
0632 static_assert(AreFunctionsCompatible<Prototype, Functor>::value,
0633 "Functor is not compatible with expected prototype!");
0634 return true;
0635 }
0636 }
0637
0638 QT_END_NAMESPACE
0639