| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2020 The Qt Company Ltd. |
| 4 | ** Copyright (C) 2019 Intel Corporation. |
| 5 | ** Contact: https://www.qt.io/licensing/ |
| 6 | ** |
| 7 | ** This file is part of the QtCore module of the Qt Toolkit. |
| 8 | ** |
| 9 | ** $QT_BEGIN_LICENSE:LGPL$ |
| 10 | ** Commercial License Usage |
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 12 | ** accordance with the commercial license agreement provided with the |
| 13 | ** Software or, alternatively, in accordance with the terms contained in |
| 14 | ** a written agreement between you and The Qt Company. For licensing terms |
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 16 | ** information use the contact form at https://www.qt.io/contact-us. |
| 17 | ** |
| 18 | ** GNU Lesser General Public License Usage |
| 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 20 | ** General Public License version 3 as published by the Free Software |
| 21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| 22 | ** packaging of this file. Please review the following information to |
| 23 | ** ensure the GNU Lesser General Public License version 3 requirements |
| 24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| 25 | ** |
| 26 | ** GNU General Public License Usage |
| 27 | ** Alternatively, this file may be used under the terms of the GNU |
| 28 | ** General Public License version 2.0 or (at your option) the GNU General |
| 29 | ** Public license version 3 or any later version approved by the KDE Free |
| 30 | ** Qt Foundation. The licenses are as published by the Free Software |
| 31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| 32 | ** included in the packaging of this file. Please review the following |
| 33 | ** information to ensure the GNU General Public License requirements will |
| 34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| 35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
| 36 | ** |
| 37 | ** $QT_END_LICENSE$ |
| 38 | ** |
| 39 | ****************************************************************************/ |
| 40 | |
| 41 | #ifndef QOBJECTDEFS_H |
| 42 | #define QOBJECTDEFS_H |
| 43 | |
| 44 | #if defined(__OBJC__) && !defined(__cplusplus) |
| 45 | # warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)" |
| 46 | #endif |
| 47 | |
| 48 | #include <QtCore/qnamespace.h> |
| 49 | #include <QtCore/qobjectdefs_impl.h> |
| 50 | #include <QtCore/qtmetamacros.h> |
| 51 | |
| 52 | QT_BEGIN_NAMESPACE |
| 53 | |
| 54 | class QByteArray; |
| 55 | struct QArrayData; |
| 56 | |
| 57 | class QString; |
| 58 | |
| 59 | #ifndef QT_NO_META_MACROS |
| 60 | // macro for onaming members |
| 61 | #ifdef METHOD |
| 62 | #undef METHOD |
| 63 | #endif |
| 64 | #ifdef SLOT |
| 65 | #undef SLOT |
| 66 | #endif |
| 67 | #ifdef SIGNAL |
| 68 | #undef SIGNAL |
| 69 | #endif |
| 70 | #endif // QT_NO_META_MACROS |
| 71 | |
| 72 | Q_CORE_EXPORT const char *qFlagLocation(const char *method); |
| 73 | |
| 74 | #ifndef QT_NO_META_MACROS |
| 75 | #ifndef QT_NO_DEBUG |
| 76 | # define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) |
| 77 | # ifndef QT_NO_KEYWORDS |
| 78 | # define METHOD(a) qFlagLocation("0"#a QLOCATION) |
| 79 | # endif |
| 80 | # define SLOT(a) qFlagLocation("1"#a QLOCATION) |
| 81 | # define SIGNAL(a) qFlagLocation("2"#a QLOCATION) |
| 82 | #else |
| 83 | # ifndef QT_NO_KEYWORDS |
| 84 | # define METHOD(a) "0"#a |
| 85 | # endif |
| 86 | # define SLOT(a) "1"#a |
| 87 | # define SIGNAL(a) "2"#a |
| 88 | #endif |
| 89 | |
| 90 | #define QMETHOD_CODE 0 // member type codes |
| 91 | #define QSLOT_CODE 1 |
| 92 | #define QSIGNAL_CODE 2 |
| 93 | #endif // QT_NO_META_MACROS |
| 94 | |
| 95 | #define Q_ARG(type, data) QArgument<type >(#type, data) |
| 96 | #define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data) |
| 97 | |
| 98 | class QObject; |
| 99 | class QMetaMethod; |
| 100 | class QMetaEnum; |
| 101 | class QMetaProperty; |
| 102 | class QMetaClassInfo; |
| 103 | |
| 104 | namespace QtPrivate { |
| 105 | class QMetaTypeInterface; |
| 106 | } |
| 107 | |
| 108 | struct QMethodRawArguments |
| 109 | { |
| 110 | void **arguments; |
| 111 | }; |
| 112 | |
| 113 | class Q_CORE_EXPORT QGenericArgument |
| 114 | { |
| 115 | public: |
| 116 | inline QGenericArgument(const char *aName = nullptr, const void *aData = nullptr) |
| 117 | : _data(aData), _name(aName) {} |
| 118 | inline void *data() const { return const_cast<void *>(_data); } |
| 119 | inline const char *name() const { return _name; } |
| 120 | |
| 121 | private: |
| 122 | const void *_data; |
| 123 | const char *_name; |
| 124 | }; |
| 125 | |
| 126 | class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument |
| 127 | { |
| 128 | public: |
| 129 | inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr) |
| 130 | : QGenericArgument(aName, aData) |
| 131 | {} |
| 132 | }; |
| 133 | |
| 134 | template <class T> |
| 135 | class QArgument: public QGenericArgument |
| 136 | { |
| 137 | public: |
| 138 | inline QArgument(const char *aName, const T &aData) |
| 139 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
| 140 | {} |
| 141 | }; |
| 142 | template <class T> |
| 143 | class QArgument<T &>: public QGenericArgument |
| 144 | { |
| 145 | public: |
| 146 | inline QArgument(const char *aName, T &aData) |
| 147 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
| 148 | {} |
| 149 | }; |
| 150 | |
| 151 | |
| 152 | template <typename T> |
| 153 | class QReturnArgument: public QGenericReturnArgument |
| 154 | { |
| 155 | public: |
| 156 | inline QReturnArgument(const char *aName, T &aData) |
| 157 | : QGenericReturnArgument(aName, static_cast<void *>(&aData)) |
| 158 | {} |
| 159 | }; |
| 160 | |
| 161 | struct Q_CORE_EXPORT QMetaObject |
| 162 | { |
| 163 | class Connection; |
| 164 | const char *className() const; |
| 165 | const QMetaObject *superClass() const; |
| 166 | |
| 167 | bool inherits(const QMetaObject *metaObject) const noexcept; |
| 168 | QObject *cast(QObject *obj) const |
| 169 | { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); } |
| 170 | const QObject *cast(const QObject *obj) const; |
| 171 | |
| 172 | #if !defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) |
| 173 | QString tr(const char *s, const char *c, int n = -1) const; |
| 174 | #endif // QT_NO_TRANSLATION |
| 175 | |
| 176 | int methodOffset() const; |
| 177 | int enumeratorOffset() const; |
| 178 | int propertyOffset() const; |
| 179 | int classInfoOffset() const; |
| 180 | |
| 181 | int constructorCount() const; |
| 182 | int methodCount() const; |
| 183 | int enumeratorCount() const; |
| 184 | int propertyCount() const; |
| 185 | int classInfoCount() const; |
| 186 | |
| 187 | int indexOfConstructor(const char *constructor) const; |
| 188 | int indexOfMethod(const char *method) const; |
| 189 | int indexOfSignal(const char *signal) const; |
| 190 | int indexOfSlot(const char *slot) const; |
| 191 | int indexOfEnumerator(const char *name) const; |
| 192 | int indexOfProperty(const char *name) const; |
| 193 | int indexOfClassInfo(const char *name) const; |
| 194 | |
| 195 | QMetaMethod constructor(int index) const; |
| 196 | QMetaMethod method(int index) const; |
| 197 | QMetaEnum enumerator(int index) const; |
| 198 | QMetaProperty property(int index) const; |
| 199 | QMetaClassInfo classInfo(int index) const; |
| 200 | QMetaProperty userProperty() const; |
| 201 | |
| 202 | static bool checkConnectArgs(const char *signal, const char *method); |
| 203 | static bool checkConnectArgs(const QMetaMethod &signal, |
| 204 | const QMetaMethod &method); |
| 205 | static QByteArray normalizedSignature(const char *method); |
| 206 | static QByteArray normalizedType(const char *type); |
| 207 | |
| 208 | // internal index-based connect |
| 209 | static Connection connect(const QObject *sender, int signal_index, |
| 210 | const QObject *receiver, int method_index, |
| 211 | int type = 0, int *types = nullptr); |
| 212 | // internal index-based disconnect |
| 213 | static bool disconnect(const QObject *sender, int signal_index, |
| 214 | const QObject *receiver, int method_index); |
| 215 | static bool disconnectOne(const QObject *sender, int signal_index, |
| 216 | const QObject *receiver, int method_index); |
| 217 | // internal slot-name based connect |
| 218 | static void connectSlotsByName(QObject *o); |
| 219 | |
| 220 | // internal index-based signal activation |
| 221 | static void activate(QObject *sender, int signal_index, void **argv); |
| 222 | static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); |
| 223 | static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); |
| 224 | |
| 225 | static bool invokeMethod(QObject *obj, const char *member, |
| 226 | Qt::ConnectionType, |
| 227 | QGenericReturnArgument ret, |
| 228 | QGenericArgument val0 = QGenericArgument(nullptr), |
| 229 | QGenericArgument val1 = QGenericArgument(), |
| 230 | QGenericArgument val2 = QGenericArgument(), |
| 231 | QGenericArgument val3 = QGenericArgument(), |
| 232 | QGenericArgument val4 = QGenericArgument(), |
| 233 | QGenericArgument val5 = QGenericArgument(), |
| 234 | QGenericArgument val6 = QGenericArgument(), |
| 235 | QGenericArgument val7 = QGenericArgument(), |
| 236 | QGenericArgument val8 = QGenericArgument(), |
| 237 | QGenericArgument val9 = QGenericArgument()); |
| 238 | |
| 239 | static inline bool invokeMethod(QObject *obj, const char *member, |
| 240 | QGenericReturnArgument ret, |
| 241 | QGenericArgument val0 = QGenericArgument(nullptr), |
| 242 | QGenericArgument val1 = QGenericArgument(), |
| 243 | QGenericArgument val2 = QGenericArgument(), |
| 244 | QGenericArgument val3 = QGenericArgument(), |
| 245 | QGenericArgument val4 = QGenericArgument(), |
| 246 | QGenericArgument val5 = QGenericArgument(), |
| 247 | QGenericArgument val6 = QGenericArgument(), |
| 248 | QGenericArgument val7 = QGenericArgument(), |
| 249 | QGenericArgument val8 = QGenericArgument(), |
| 250 | QGenericArgument val9 = QGenericArgument()) |
| 251 | { |
| 252 | return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3, |
| 253 | val4, val5, val6, val7, val8, val9); |
| 254 | } |
| 255 | |
| 256 | static inline bool invokeMethod(QObject *obj, const char *member, |
| 257 | Qt::ConnectionType type, |
| 258 | QGenericArgument val0 = QGenericArgument(nullptr), |
| 259 | QGenericArgument val1 = QGenericArgument(), |
| 260 | QGenericArgument val2 = QGenericArgument(), |
| 261 | QGenericArgument val3 = QGenericArgument(), |
| 262 | QGenericArgument val4 = QGenericArgument(), |
| 263 | QGenericArgument val5 = QGenericArgument(), |
| 264 | QGenericArgument val6 = QGenericArgument(), |
| 265 | QGenericArgument val7 = QGenericArgument(), |
| 266 | QGenericArgument val8 = QGenericArgument(), |
| 267 | QGenericArgument val9 = QGenericArgument()) |
| 268 | { |
| 269 | return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2, |
| 270 | val3, val4, val5, val6, val7, val8, val9); |
| 271 | } |
| 272 | |
| 273 | static inline bool invokeMethod(QObject *obj, const char *member, |
| 274 | QGenericArgument val0 = QGenericArgument(nullptr), |
| 275 | QGenericArgument val1 = QGenericArgument(), |
| 276 | QGenericArgument val2 = QGenericArgument(), |
| 277 | QGenericArgument val3 = QGenericArgument(), |
| 278 | QGenericArgument val4 = QGenericArgument(), |
| 279 | QGenericArgument val5 = QGenericArgument(), |
| 280 | QGenericArgument val6 = QGenericArgument(), |
| 281 | QGenericArgument val7 = QGenericArgument(), |
| 282 | QGenericArgument val8 = QGenericArgument(), |
| 283 | QGenericArgument val9 = QGenericArgument()) |
| 284 | { |
| 285 | return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0, |
| 286 | val1, val2, val3, val4, val5, val6, val7, val8, val9); |
| 287 | } |
| 288 | |
| 289 | #ifdef Q_CLANG_QDOC |
| 290 | template<typename Functor, typename FunctorReturnType> |
| 291 | static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); |
| 292 | template<typename Functor, typename FunctorReturnType> |
| 293 | static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret); |
| 294 | #else |
| 295 | |
| 296 | // invokeMethod() for member function pointer |
| 297 | template <typename Func> |
| 298 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 299 | && !std::is_convertible<Func, const char*>::value |
| 300 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
| 301 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
| 302 | Func function, |
| 303 | Qt::ConnectionType type = Qt::AutoConnection, |
| 304 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
| 305 | { |
| 306 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret); |
| 307 | } |
| 308 | |
| 309 | template <typename Func> |
| 310 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 311 | && !std::is_convertible<Func, const char*>::value |
| 312 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
| 313 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
| 314 | Func function, |
| 315 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
| 316 | { |
| 317 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret); |
| 318 | } |
| 319 | |
| 320 | // invokeMethod() for function pointer (not member) |
| 321 | template <typename Func> |
| 322 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 323 | && !std::is_convertible<Func, const char*>::value |
| 324 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
| 325 | invokeMethod(QObject *context, Func function, |
| 326 | Qt::ConnectionType type = Qt::AutoConnection, |
| 327 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
| 328 | { |
| 329 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret); |
| 330 | } |
| 331 | |
| 332 | template <typename Func> |
| 333 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 334 | && !std::is_convertible<Func, const char*>::value |
| 335 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
| 336 | invokeMethod(QObject *context, Func function, |
| 337 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
| 338 | { |
| 339 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret); |
| 340 | } |
| 341 | |
| 342 | // invokeMethod() for Functor |
| 343 | template <typename Func> |
| 344 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 345 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
| 346 | && !std::is_convertible<Func, const char*>::value, bool>::type |
| 347 | invokeMethod(QObject *context, Func function, |
| 348 | Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) |
| 349 | { |
| 350 | return invokeMethodImpl(context, |
| 351 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
| 352 | type, |
| 353 | ret); |
| 354 | } |
| 355 | |
| 356 | template <typename Func> |
| 357 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
| 358 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
| 359 | && !std::is_convertible<Func, const char*>::value, bool>::type |
| 360 | invokeMethod(QObject *context, Func function, decltype(function()) *ret) |
| 361 | { |
| 362 | return invokeMethodImpl(context, |
| 363 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
| 364 | Qt::AutoConnection, |
| 365 | ret); |
| 366 | } |
| 367 | |
| 368 | #endif |
| 369 | |
| 370 | QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr), |
| 371 | QGenericArgument val1 = QGenericArgument(), |
| 372 | QGenericArgument val2 = QGenericArgument(), |
| 373 | QGenericArgument val3 = QGenericArgument(), |
| 374 | QGenericArgument val4 = QGenericArgument(), |
| 375 | QGenericArgument val5 = QGenericArgument(), |
| 376 | QGenericArgument val6 = QGenericArgument(), |
| 377 | QGenericArgument val7 = QGenericArgument(), |
| 378 | QGenericArgument val8 = QGenericArgument(), |
| 379 | QGenericArgument val9 = QGenericArgument()) const; |
| 380 | |
| 381 | enum Call { |
| 382 | InvokeMetaMethod, |
| 383 | ReadProperty, |
| 384 | WriteProperty, |
| 385 | ResetProperty, |
| 386 | CreateInstance, |
| 387 | IndexOfMethod, |
| 388 | RegisterPropertyMetaType, |
| 389 | RegisterMethodArgumentMetaType, |
| 390 | BindableProperty |
| 391 | }; |
| 392 | |
| 393 | int static_metacall(Call, int, void **) const; |
| 394 | static int metacall(QObject *, Call, int, void **); |
| 395 | |
| 396 | template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject() |
| 397 | { |
| 398 | return &MO; |
| 399 | } |
| 400 | |
| 401 | struct SuperData { |
| 402 | const QMetaObject *direct; |
| 403 | SuperData() = default; |
| 404 | constexpr SuperData(std::nullptr_t) : direct(nullptr) {} |
| 405 | constexpr SuperData(const QMetaObject *mo) : direct(mo) {} |
| 406 | |
| 407 | constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } |
| 408 | |
| 409 | #ifdef QT_NO_DATA_RELOCATION |
| 410 | using Getter = const QMetaObject *(*)(); |
| 411 | Getter indirect = nullptr; |
| 412 | constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} |
| 413 | constexpr operator const QMetaObject *() const |
| 414 | { return indirect ? indirect() : direct; } |
| 415 | template <const QMetaObject &MO> static constexpr SuperData link() |
| 416 | { return SuperData(QMetaObject::staticMetaObject<MO>); } |
| 417 | #else |
| 418 | constexpr operator const QMetaObject *() const |
| 419 | { return direct; } |
| 420 | template <const QMetaObject &MO> static constexpr SuperData link() |
| 421 | { return SuperData(QMetaObject::staticMetaObject<MO>()); } |
| 422 | #endif |
| 423 | }; |
| 424 | |
| 425 | struct Data { // private data |
| 426 | SuperData superdata; |
| 427 | const uint *stringdata; |
| 428 | const uint *data; |
| 429 | typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); |
| 430 | StaticMetacallFunction static_metacall; |
| 431 | const SuperData *relatedMetaObjects; |
| 432 | const QtPrivate::QMetaTypeInterface *const *metaTypes; |
| 433 | void *; //reserved for future use |
| 434 | } d; |
| 435 | |
| 436 | private: |
| 437 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); |
| 438 | friend class QTimer; |
| 439 | }; |
| 440 | |
| 441 | class Q_CORE_EXPORT QMetaObject::Connection { |
| 442 | void *d_ptr; //QObjectPrivate::Connection* |
| 443 | explicit Connection(void *data) : d_ptr(data) { } |
| 444 | friend class QObject; |
| 445 | friend class QObjectPrivate; |
| 446 | friend struct QMetaObject; |
| 447 | bool isConnected_helper() const; |
| 448 | public: |
| 449 | ~Connection(); |
| 450 | Connection(); |
| 451 | Connection(const Connection &other); |
| 452 | Connection &operator=(const Connection &other); |
| 453 | #ifdef Q_QDOC |
| 454 | operator bool() const; |
| 455 | #else |
| 456 | // still using the restricted bool trick here, in order to support |
| 457 | // code using copy-init (e.g. `bool ok = connect(...)`) |
| 458 | typedef void *Connection::*RestrictedBool; |
| 459 | operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } |
| 460 | #endif |
| 461 | |
| 462 | Connection(Connection &&o) noexcept : d_ptr(qExchange(o.d_ptr, nullptr)) {} |
| 463 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) |
| 464 | void swap(Connection &o) noexcept { qSwap(d_ptr, o.d_ptr); } |
| 465 | }; |
| 466 | |
| 467 | inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept |
| 468 | { |
| 469 | lhs.swap(rhs); |
| 470 | } |
| 471 | |
| 472 | inline const QMetaObject *QMetaObject::superClass() const |
| 473 | { return d.superdata; } |
| 474 | |
| 475 | namespace QtPrivate { |
| 476 | /* Trait that tells is a the Object has a Q_OBJECT macro */ |
| 477 | template <typename Object> struct HasQ_OBJECT_Macro { |
| 478 | template <typename T> |
| 479 | static char test(int (T::*)(QMetaObject::Call, int, void **)); |
| 480 | static int test(int (Object::*)(QMetaObject::Call, int, void **)); |
| 481 | enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) }; |
| 482 | }; |
| 483 | } |
| 484 | |
| 485 | QT_END_NAMESPACE |
| 486 | |
| 487 | #endif // QOBJECTDEFS_H |
| 488 | |