1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QOBJECTDEFS_H
6#define QOBJECTDEFS_H
7
8#if defined(__OBJC__) && !defined(__cplusplus)
9# warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)"
10#endif
11
12#include <QtCore/qnamespace.h>
13#include <QtCore/qobjectdefs_impl.h>
14#include <QtCore/qtcoreexports.h>
15#include <QtCore/qtmetamacros.h>
16
17QT_BEGIN_NAMESPACE
18
19class QByteArray;
20struct QArrayData;
21
22class QString;
23
24#ifndef QT_NO_META_MACROS
25// macro for onaming members
26#ifdef METHOD
27#undef METHOD
28#endif
29#ifdef SLOT
30#undef SLOT
31#endif
32#ifdef SIGNAL
33#undef SIGNAL
34#endif
35#endif // QT_NO_META_MACROS
36
37Q_CORE_EXPORT const char *qFlagLocation(const char *method);
38
39#ifndef QT_NO_META_MACROS
40# define QMETHOD_CODE 0 // member type codes
41# define QSLOT_CODE 1
42# define QSIGNAL_CODE 2
43# define QT_PREFIX_CODE(code, a) QT_STRINGIFY(code) #a
44# define QT_STRINGIFY_METHOD(a) QT_PREFIX_CODE(QMETHOD_CODE, a)
45# define QT_STRINGIFY_SLOT(a) QT_PREFIX_CODE(QSLOT_CODE, a)
46# define QT_STRINGIFY_SIGNAL(a) QT_PREFIX_CODE(QSIGNAL_CODE, a)
47# ifndef QT_NO_DEBUG
48# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
49# ifndef QT_NO_KEYWORDS
50# define METHOD(a) qFlagLocation(QT_STRINGIFY_METHOD(a) QLOCATION)
51# endif
52# define SLOT(a) qFlagLocation(QT_STRINGIFY_SLOT(a) QLOCATION)
53# define SIGNAL(a) qFlagLocation(QT_STRINGIFY_SIGNAL(a) QLOCATION)
54# else
55# ifndef QT_NO_KEYWORDS
56# define METHOD(a) QT_STRINGIFY_METHOD(a)
57# endif
58# define SLOT(a) QT_STRINGIFY_SLOT(a)
59# define SIGNAL(a) QT_STRINGIFY_SIGNAL(a)
60# endif
61#endif // QT_NO_META_MACROS
62
63#define Q_ARG(Type, data) QtPrivate::Invoke::argument<Type>(QT_STRINGIFY(Type), data)
64#define Q_RETURN_ARG(Type, data) QtPrivate::Invoke::returnArgument<Type>(QT_STRINGIFY(Type), data)
65
66class QObject;
67class QMetaMethod;
68class QMetaEnum;
69class QMetaProperty;
70class QMetaClassInfo;
71
72namespace QtPrivate {
73class QMetaTypeInterface;
74template<typename T> constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
75}
76
77struct QMethodRawArguments
78{
79 void **arguments;
80};
81
82#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
83class Q_CORE_EXPORT QGenericArgument
84{
85public:
86 inline QGenericArgument(const char *aName = nullptr, const void *aData = nullptr)
87 : _data(aData), _name(aName) {}
88 inline void *data() const { return const_cast<void *>(_data); }
89 inline const char *name() const { return _name; }
90
91private:
92 const void *_data;
93 const char *_name;
94};
95
96class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument
97{
98public:
99 inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr)
100 : QGenericArgument(aName, aData)
101 {}
102};
103
104template <class T>
105class QArgument: public QGenericArgument
106{
107public:
108 inline QArgument(const char *aName, const T &aData)
109 : QGenericArgument(aName, static_cast<const void *>(&aData))
110 {}
111};
112template <class T>
113class QArgument<T &>: public QGenericArgument
114{
115public:
116 inline QArgument(const char *aName, T &aData)
117 : QGenericArgument(aName, static_cast<const void *>(&aData))
118 {}
119};
120
121
122template <typename T>
123class QReturnArgument: public QGenericReturnArgument
124{
125public:
126 inline QReturnArgument(const char *aName, T &aData)
127 : QGenericReturnArgument(aName, static_cast<void *>(&aData))
128 {}
129};
130#endif
131
132struct QMetaMethodArgument
133{
134 const QtPrivate::QMetaTypeInterface *metaType;
135 const char *name;
136 const void *data;
137};
138
139struct QMetaMethodReturnArgument
140{
141 const QtPrivate::QMetaTypeInterface *metaType;
142 const char *name;
143 void *data;
144};
145
146template <typename T>
147struct QTemplatedMetaMethodReturnArgument : QMetaMethodReturnArgument
148{
149 using Type = T;
150};
151
152namespace QtPrivate {
153namespace Invoke {
154#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
155template <typename... Args>
156using AreOldStyleArgs = std::disjunction<std::is_base_of<QGenericArgument, Args>...>;
157
158template <typename T, typename... Args> using IfNotOldStyleArgs =
159 std::enable_if_t<!AreOldStyleArgs<Args...>::value, T>;
160#else
161template <typename T, typename... Args> using IfNotOldStyleArgs = T;
162#endif
163
164template <typename T> inline QMetaMethodArgument argument(const char *name, const T &t)
165{
166 if constexpr ((std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) ||
167 !std::is_reference_v<T>) {
168 return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) };
169 } else {
170 return { nullptr, name, std::addressof(t) };
171 }
172}
173
174template <typename T>
175inline QTemplatedMetaMethodReturnArgument<T> returnArgument(const char *name, T &t)
176{
177 return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) };
178}
179
180template <typename T> inline const char *typenameHelper(const T &)
181{
182 return nullptr;
183}
184template <typename T> inline const void *dataHelper(const T &t)
185{
186 return std::addressof(t);
187}
188template <typename T> inline const QMetaTypeInterface *metaTypeHelper(const T &)
189{
190 return qMetaTypeInterfaceForType<T>();
191}
192
193inline const char *typenameHelper(QMetaMethodArgument a)
194{ return a.name; }
195inline const void *dataHelper(QMetaMethodArgument a)
196{ return a.data; }
197inline const QMetaTypeInterface *metaTypeHelper(QMetaMethodArgument a)
198{ return a.metaType; }
199
200inline const char *typenameHelper(const char *) = delete;
201template <typename T> inline const void *dataHelper(const char *) = delete;
202inline const QMetaTypeInterface *metaTypeHelper(const char *) = delete;
203inline const char *typenameHelper(const char16_t *) = delete;
204template <typename T> inline const void *dataHelper(const char16_t *) = delete;
205inline const QMetaTypeInterface *metaTypeHelper(const char16_t *) = delete;
206
207} // namespace QtPrivate::Invoke
208
209template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments)
210{
211 std::array params = { const_cast<const void *>(r.data), Invoke::dataHelper(arguments)... };
212 std::array names = { r.name, Invoke::typenameHelper(arguments)... };
213 std::array types = { r.metaType, Invoke::metaTypeHelper(arguments)... };
214 static_assert(params.size() == types.size());
215 static_assert(params.size() == names.size());
216
217 struct R {
218 decltype(params) parameters;
219 decltype(names) typeNames;
220 decltype(types) metaTypes;
221 constexpr qsizetype parameterCount() const { return qsizetype(parameters.size()); }
222 };
223 return R { params, names, types };
224}
225} // namespace QtPrivate
226
227template <typename T> void qReturnArg(const T &&) = delete;
228template <typename T> inline QTemplatedMetaMethodReturnArgument<T> qReturnArg(T &data)
229{
230 return QtPrivate::Invoke::returnArgument(nullptr, data);
231}
232
233struct Q_CORE_EXPORT QMetaObject
234{
235 class Connection;
236 const char *className() const;
237 const QMetaObject *superClass() const;
238
239 bool inherits(const QMetaObject *metaObject) const noexcept;
240 QObject *cast(QObject *obj) const
241 { return const_cast<QObject *>(cast(obj: const_cast<const QObject *>(obj))); }
242 const QObject *cast(const QObject *obj) const;
243
244#if !defined(QT_NO_TRANSLATION) || defined(Q_QDOC)
245 QString tr(const char *s, const char *c, int n = -1) const;
246#endif // QT_NO_TRANSLATION
247
248 QMetaType metaType() const;
249
250 int methodOffset() const;
251 int enumeratorOffset() const;
252 int propertyOffset() const;
253 int classInfoOffset() const;
254
255 int constructorCount() const;
256 int methodCount() const;
257 int enumeratorCount() const;
258 int propertyCount() const;
259 int classInfoCount() const;
260
261 int indexOfConstructor(const char *constructor) const;
262 int indexOfMethod(const char *method) const;
263 int indexOfSignal(const char *signal) const;
264 int indexOfSlot(const char *slot) const;
265 int indexOfEnumerator(const char *name) const;
266
267 int indexOfProperty(const char *name) const;
268 int indexOfClassInfo(const char *name) const;
269
270 QMetaMethod constructor(int index) const;
271 QMetaMethod method(int index) const;
272 QMetaEnum enumerator(int index) const;
273 QMetaProperty property(int index) const;
274 QMetaClassInfo classInfo(int index) const;
275 QMetaProperty userProperty() const;
276
277 static bool checkConnectArgs(const char *signal, const char *method);
278 static bool checkConnectArgs(const QMetaMethod &signal,
279 const QMetaMethod &method);
280 static QByteArray normalizedSignature(const char *method);
281 static QByteArray normalizedType(const char *type);
282
283 // internal index-based connect
284 static Connection connect(const QObject *sender, int signal_index,
285 const QObject *receiver, int method_index,
286 int type = 0, int *types = nullptr);
287 // internal index-based disconnect
288 static bool disconnect(const QObject *sender, int signal_index,
289 const QObject *receiver, int method_index);
290 static bool disconnectOne(const QObject *sender, int signal_index,
291 const QObject *receiver, int method_index);
292 // internal slot-name based connect
293 static void connectSlotsByName(QObject *o);
294
295 // internal index-based signal activation
296 static void activate(QObject *sender, int signal_index, void **argv);
297 static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
298 static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv);
299
300#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
301 static bool invokeMethod(QObject *obj, const char *member,
302 Qt::ConnectionType,
303 QGenericReturnArgument ret,
304 QGenericArgument val0 = QGenericArgument(nullptr),
305 QGenericArgument val1 = QGenericArgument(),
306 QGenericArgument val2 = QGenericArgument(),
307 QGenericArgument val3 = QGenericArgument(),
308 QGenericArgument val4 = QGenericArgument(),
309 QGenericArgument val5 = QGenericArgument(),
310 QGenericArgument val6 = QGenericArgument(),
311 QGenericArgument val7 = QGenericArgument(),
312 QGenericArgument val8 = QGenericArgument(),
313 QGenericArgument val9 = QGenericArgument());
314
315 static inline bool invokeMethod(QObject *obj, const char *member,
316 QGenericReturnArgument ret,
317 QGenericArgument val0 = QGenericArgument(nullptr),
318 QGenericArgument val1 = QGenericArgument(),
319 QGenericArgument val2 = QGenericArgument(),
320 QGenericArgument val3 = QGenericArgument(),
321 QGenericArgument val4 = QGenericArgument(),
322 QGenericArgument val5 = QGenericArgument(),
323 QGenericArgument val6 = QGenericArgument(),
324 QGenericArgument val7 = QGenericArgument(),
325 QGenericArgument val8 = QGenericArgument(),
326 QGenericArgument val9 = QGenericArgument())
327 {
328 return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
329 val4, val5, val6, val7, val8, val9);
330 }
331
332 static inline bool invokeMethod(QObject *obj, const char *member,
333 Qt::ConnectionType type,
334 QGenericArgument val0,
335 QGenericArgument val1 = QGenericArgument(),
336 QGenericArgument val2 = QGenericArgument(),
337 QGenericArgument val3 = QGenericArgument(),
338 QGenericArgument val4 = QGenericArgument(),
339 QGenericArgument val5 = QGenericArgument(),
340 QGenericArgument val6 = QGenericArgument(),
341 QGenericArgument val7 = QGenericArgument(),
342 QGenericArgument val8 = QGenericArgument(),
343 QGenericArgument val9 = QGenericArgument())
344 {
345 return invokeMethod(obj, member, type, ret: QGenericReturnArgument(), val0, val1, val2,
346 val3, val4, val5, val6, val7, val8, val9);
347 }
348
349 static inline bool invokeMethod(QObject *obj, const char *member,
350 QGenericArgument val0,
351 QGenericArgument val1 = QGenericArgument(),
352 QGenericArgument val2 = QGenericArgument(),
353 QGenericArgument val3 = QGenericArgument(),
354 QGenericArgument val4 = QGenericArgument(),
355 QGenericArgument val5 = QGenericArgument(),
356 QGenericArgument val6 = QGenericArgument(),
357 QGenericArgument val7 = QGenericArgument(),
358 QGenericArgument val8 = QGenericArgument(),
359 QGenericArgument val9 = QGenericArgument())
360 {
361 return invokeMethod(obj, member, Qt::AutoConnection, ret: QGenericReturnArgument(), val0,
362 val1, val2, val3, val4, val5, val6, val7, val8, val9);
363 }
364#endif // Qt < 7.0
365
366 template <typename ReturnArg, typename... Args> static
367#ifdef Q_QDOC
368 bool
369#else
370 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
371#endif
372 invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c,
373 QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments)
374 {
375 auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
376 return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(),
377 h.typeNames.data(), h.metaTypes.data());
378 }
379
380 template <typename... Args> static
381#ifdef Q_QDOC
382 bool
383#else
384 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
385#endif
386 invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments)
387 {
388 QTemplatedMetaMethodReturnArgument<void> r = {};
389 return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...);
390 }
391
392 template <typename ReturnArg, typename... Args> static
393#ifdef Q_QDOC
394 bool
395#else
396 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
397#endif
398 invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> r,
399 Args &&... arguments)
400 {
401 return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
402 }
403
404 template <typename... Args> static
405#ifdef Q_QDOC
406 bool
407#else
408 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
409#endif
410 invokeMethod(QObject *obj, const char *member, Args &&... arguments)
411 {
412 QTemplatedMetaMethodReturnArgument<void> r = {};
413 return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
414 }
415
416#ifdef Q_QDOC
417 template<typename Functor, typename FunctorReturnType>
418 static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr);
419 template<typename Functor, typename FunctorReturnType>
420 static bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret);
421
422 template<typename Functor, typename FunctorReturnType, typename... Args>
423 static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments);
424 template<typename Functor, typename FunctorReturnType, typename... Args>
425 static bool invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments);
426 template<typename Functor, typename... Args>
427 static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments);
428 template<typename Functor, typename... Args>
429 static bool invokeMethod(QObject *context, Functor &&function, Args &&...arguments);
430#else
431 template <typename Func>
432 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
433 QtPrivate::Invoke::AreOldStyleArgs<Func>>,
434 bool>
435 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
436 Func &&function, Qt::ConnectionType type,
437 typename QtPrivate::Callable<Func>::ReturnType *ret)
438 {
439 using R = typename QtPrivate::Callable<Func>::ReturnType;
440 const auto getReturnArg = [ret]() -> QTemplatedMetaMethodReturnArgument<R> {
441 if constexpr (std::is_void_v<R>)
442 return {};
443 else
444 return ret ? qReturnArg(*ret) : QTemplatedMetaMethodReturnArgument<R>{};
445 };
446 return invokeMethod(object, std::forward<Func>(function), type, getReturnArg());
447 }
448 template <typename Func>
449 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
450 QtPrivate::Invoke::AreOldStyleArgs<Func>>,
451 bool>
452 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
453 Func &&function, typename QtPrivate::Callable<Func>::ReturnType *ret)
454 {
455 return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret);
456 }
457
458 template <typename Func, typename... Args>
459 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
460 QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
461 bool>
462 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
463 Func &&function, Qt::ConnectionType type,
464 QTemplatedMetaMethodReturnArgument<
465 typename QtPrivate::Callable<Func, Args...>::ReturnType>
466 ret,
467 Args &&...args)
468 {
469 return invokeMethodCallableHelper(object, std::forward<Func>(function), type, ret,
470 std::forward<Args>(args)...);
471 }
472
473 template <typename Func, typename... Args>
474 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
475 QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
476 bool>
477 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
478 Func &&function, Qt::ConnectionType type, Args &&...args)
479 {
480 using R = typename QtPrivate::Callable<Func, Args...>::ReturnType;
481 QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr,
482 nullptr };
483 return invokeMethod(object, std::forward<Func>(function), type, r,
484 std::forward<Args>(args)...);
485 }
486
487 template <typename Func, typename... Args>
488 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
489 QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
490 bool>
491 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
492 Func &&function,
493 QTemplatedMetaMethodReturnArgument<
494 typename QtPrivate::Callable<Func, Args...>::ReturnType>
495 ret,
496 Args &&...args)
497 {
498 return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret,
499 std::forward<Args>(args)...);
500 }
501
502 template <typename Func, typename... Args>
503 static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>,
504 QtPrivate::Invoke::AreOldStyleArgs<Args...>>,
505 bool>
506 invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
507 Func &&function, Args &&...args)
508 {
509 using R = typename QtPrivate::Callable<Func, Args...>::ReturnType;
510 QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr,
511 nullptr };
512 return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, r,
513 std::forward<Args>(args)...);
514 }
515
516#endif
517
518#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
519 QObject *newInstance(QGenericArgument val0,
520 QGenericArgument val1 = QGenericArgument(),
521 QGenericArgument val2 = QGenericArgument(),
522 QGenericArgument val3 = QGenericArgument(),
523 QGenericArgument val4 = QGenericArgument(),
524 QGenericArgument val5 = QGenericArgument(),
525 QGenericArgument val6 = QGenericArgument(),
526 QGenericArgument val7 = QGenericArgument(),
527 QGenericArgument val8 = QGenericArgument(),
528 QGenericArgument val9 = QGenericArgument()) const;
529#endif
530
531 template <typename... Args>
532#ifdef Q_QDOC
533 QObject *
534#else
535 QtPrivate::Invoke::IfNotOldStyleArgs<QObject *, Args...>
536#endif
537 newInstance(Args &&... arguments) const
538 {
539 auto h = QtPrivate::invokeMethodHelper(QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...);
540 return newInstanceImpl(mobj: this, parameterCount: h.parameterCount(), parameters: h.parameters.data(),
541 typeNames: h.typeNames.data(), metaTypes: h.metaTypes.data());
542 }
543
544 enum Call {
545 InvokeMetaMethod,
546 ReadProperty,
547 WriteProperty,
548 ResetProperty,
549 CreateInstance,
550 IndexOfMethod,
551 RegisterPropertyMetaType,
552 RegisterMethodArgumentMetaType,
553 BindableProperty,
554 CustomCall,
555 ConstructInPlace,
556 };
557
558 int static_metacall(Call, int, void **) const;
559 static int metacall(QObject *, Call, int, void **);
560
561 template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject()
562 {
563 return &MO;
564 }
565
566 struct SuperData {
567 using Getter = const QMetaObject *(*)();
568 const QMetaObject *direct;
569 SuperData() = default;
570 constexpr SuperData(std::nullptr_t) : direct(nullptr) {}
571 constexpr SuperData(const QMetaObject *mo) : direct(mo) {}
572
573 constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); }
574
575#ifdef QT_NO_DATA_RELOCATION
576 Getter indirect = nullptr;
577 constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {}
578 constexpr operator const QMetaObject *() const
579 { return indirect ? indirect() : direct; }
580 template <const QMetaObject &MO> static constexpr SuperData link()
581 { return SuperData(QMetaObject::staticMetaObject<MO>); }
582#else
583 constexpr SuperData(Getter g) : direct(g()) {}
584 constexpr operator const QMetaObject *() const
585 { return direct; }
586 template <const QMetaObject &MO> static constexpr SuperData link()
587 { return SuperData(QMetaObject::staticMetaObject<MO>()); }
588#endif
589 };
590
591 struct Data { // private data
592 SuperData superdata;
593 const uint *stringdata;
594 const uint *data;
595 typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
596 StaticMetacallFunction static_metacall;
597 const SuperData *relatedMetaObjects;
598 const QtPrivate::QMetaTypeInterface *const *metaTypes;
599 void *extradata; //reserved for future use
600 } d;
601
602private:
603 // Just need to have this here with a separate name so the other inline
604 // functions can call this without any ambiguity
605 template <typename Func, typename... Args>
606 static bool
607 invokeMethodCallableHelper(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object,
608 Func &&function, Qt::ConnectionType type, const QMetaMethodReturnArgument &ret,
609 Args &&...args)
610 {
611 using Callable = QtPrivate::Callable<Func, Args...>;
612 using ExpectedArguments = typename Callable::Arguments;
613 static_assert(sizeof...(Args) <= ExpectedArguments::size, "Too many arguments");
614 using ActualArguments = QtPrivate::List<Args...>;
615 static_assert(QtPrivate::CheckCompatibleArguments<ActualArguments,
616 ExpectedArguments>::value,
617 "Incompatible arguments");
618
619 auto h = QtPrivate::invokeMethodHelper(ret, std::forward<Args>(args)...);
620
621 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
622 auto callable = new QtPrivate::QCallableObject<std::decay_t<Func>, ActualArguments,
623 typename Callable::ReturnType>(std::forward<Func>(function));
624 return invokeMethodImpl(object, callable, type, h.parameterCount(), h.parameters.data(),
625 h.typeNames.data(), h.metaTypes.data());
626 }
627
628 static bool invokeMethodImpl(QObject *object, const char *member, Qt::ConnectionType type,
629 qsizetype parameterCount, const void *const *parameters, const char *const *names,
630 const QtPrivate::QMetaTypeInterface * const *metaTypes);
631 static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj,
632 Qt::ConnectionType type, qsizetype parameterCount,
633 const void *const *params, const char *const *names,
634 const QtPrivate::QMetaTypeInterface *const *metaTypes);
635#if QT_CORE_REMOVED_SINCE(6, 7)
636 static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
637#endif
638 static QObject *newInstanceImpl(const QMetaObject *mobj, qsizetype parameterCount,
639 const void **parameters, const char **typeNames,
640 const QtPrivate::QMetaTypeInterface **metaTypes);
641 friend class QTimer;
642};
643
644class Q_CORE_EXPORT QMetaObject::Connection {
645 void *d_ptr; //QObjectPrivate::Connection*
646 explicit Connection(void *data) : d_ptr(data) { }
647 friend class QObject;
648 friend class QObjectPrivate;
649 friend struct QMetaObject;
650 bool isConnected_helper() const;
651public:
652 ~Connection();
653 Connection();
654 Connection(const Connection &other);
655 Connection &operator=(const Connection &other);
656#ifdef Q_QDOC
657 operator bool() const;
658#else
659 // still using the restricted bool trick here, in order to support
660 // code using copy-init (e.g. `bool ok = connect(...)`)
661 typedef void *Connection::*RestrictedBool;
662 operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; }
663#endif
664
665 Connection(Connection &&other) noexcept : d_ptr(std::exchange(obj&: other.d_ptr, new_val: nullptr)) {}
666 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection)
667 void swap(Connection &other) noexcept { qt_ptr_swap(lhs&: d_ptr, rhs&: other.d_ptr); }
668};
669
670inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept
671{
672 lhs.swap(other&: rhs);
673}
674
675inline const QMetaObject *QMetaObject::superClass() const
676{ return d.superdata; }
677
678namespace QtPrivate {
679 // Trait that tells if a QObject has a Q_OBJECT macro
680 template <typename Object> struct HasQ_OBJECT_Macro {
681 template <typename T>
682 static char test(int (T::*)(QMetaObject::Call, int, void **));
683 static int test(int (Object::*)(QMetaObject::Call, int, void **));
684 enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) };
685 };
686}
687
688QT_END_NAMESPACE
689
690#endif // QOBJECTDEFS_H
691