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