1 /* 2 * DQt - D bindings for the Qt Toolkit 3 * 4 * GNU Lesser General Public License Usage 5 * This file may be used under the terms of the GNU Lesser 6 * General Public License version 3 as published by the Free Software 7 * Foundation and appearing in the file LICENSE.LGPL3 included in the 8 * packaging of this file. Please review the following information to 9 * ensure the GNU Lesser General Public License version 3 requirements 10 * will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 11 */ 12 module qt.core.metatype; 13 extern(C++): 14 15 import qt.config; 16 import qt.core.basicatomic; 17 import qt.core.bytearray; 18 import qt.core.bytearrayview; 19 import qt.core.compare; 20 import qt.core.datastream; 21 import qt.core.flags; 22 import qt.core.global; 23 import qt.core.iterable; 24 import qt.core.object; 25 import qt.core.objectdefs; 26 import qt.core.typeinfo; 27 import qt.helpers; 28 import std.traits; 29 30 /+ #ifndef QT_NO_QOBJECT 31 #endif 32 33 #ifdef Bool 34 #error qmetatype.h must be included before any header file that defines Bool 35 #endif 36 37 38 // from qcborcommon.h 39 enum class QCborSimpleType : quint8; 40 41 42 template <typename T> 43 inline constexpr int qMetaTypeId(); 44 +/ 45 46 struct BuiltinTypeInfo 47 { 48 string typeName; 49 int typeNameID; 50 string realType; 51 string dType; 52 } 53 54 // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType) 55 enum immutable(BuiltinTypeInfo[]) primitiveTypes = [ 56 BuiltinTypeInfo("Void", 43, "void"), 57 BuiltinTypeInfo("Bool", 1, "bool"), 58 BuiltinTypeInfo("Int", 2, "int"), 59 BuiltinTypeInfo("UInt", 3, "uint"), 60 BuiltinTypeInfo("LongLong", 4, "qlonglong"), 61 BuiltinTypeInfo("ULongLong", 5, "qulonglong"), 62 BuiltinTypeInfo("Double", 6, "double"), 63 BuiltinTypeInfo("Long", 32, "long"), 64 BuiltinTypeInfo("Short", 33, "short"), 65 BuiltinTypeInfo("Char", 34, "char"), 66 BuiltinTypeInfo("Char16", 56, "char16_t", "wchar"), 67 BuiltinTypeInfo("Char32", 57, "char32_t", "dchar"), 68 BuiltinTypeInfo("ULong", 35, "ulong"), 69 BuiltinTypeInfo("UShort", 36, "ushort"), 70 BuiltinTypeInfo("UChar", 37, "uchar"), 71 BuiltinTypeInfo("Float", 38, "float"), 72 BuiltinTypeInfo("SChar", 40, "signed char", "byte"), 73 BuiltinTypeInfo("Nullptr", 51, "std::nullptr_t", "typeof(null)"), 74 BuiltinTypeInfo("QCborSimpleType", 52, "QCborSimpleType"), 75 ]; 76 77 enum immutable(BuiltinTypeInfo[]) primitivePointerTypes = [ 78 BuiltinTypeInfo("VoidStar", 31, "void*"), 79 ]; 80 81 /+ #if QT_CONFIG(easingcurve) +/ 82 enum immutable(BuiltinTypeInfo[]) easingCurveTypes = [ 83 BuiltinTypeInfo("QEasingCurve", 29, "QEasingCurve"), 84 ]; 85 /+ #else 86 #define QT_FOR_EACH_STATIC_EASINGCURVE(F) 87 #endif +/ 88 89 /+ #if QT_CONFIG(itemmodel) +/ 90 enum immutable(BuiltinTypeInfo[]) itemModelClasses = [ 91 BuiltinTypeInfo("QModelIndex", 42, "QModelIndex"), 92 BuiltinTypeInfo("QPersistentModelIndex", 50, "QPersistentModelIndex"), 93 ]; 94 /+ #else 95 #define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F) 96 #endif +/ 97 98 /+ #if QT_CONFIG(regularexpression) +/ 99 enum immutable(BuiltinTypeInfo[]) regularExpressionTypes = [ 100 BuiltinTypeInfo("QRegularExpression", 44, "QRegularExpression"), 101 ]; 102 /+ #else 103 # define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) 104 #endif +/ 105 106 enum immutable(BuiltinTypeInfo[]) coreClasses = [ 107 BuiltinTypeInfo("QChar", 7, "QChar"), 108 BuiltinTypeInfo("QString", 10, "QString"), 109 BuiltinTypeInfo("QByteArray", 12, "QByteArray"), 110 BuiltinTypeInfo("QBitArray", 13, "QBitArray"), 111 BuiltinTypeInfo("QDate", 14, "QDate"), 112 BuiltinTypeInfo("QTime", 15, "QTime"), 113 BuiltinTypeInfo("QDateTime", 16, "QDateTime"), 114 BuiltinTypeInfo("QUrl", 17, "QUrl"), 115 BuiltinTypeInfo("QLocale", 18, "QLocale"), 116 BuiltinTypeInfo("QRect", 19, "QRect"), 117 BuiltinTypeInfo("QRectF", 20, "QRectF"), 118 BuiltinTypeInfo("QSize", 21, "QSize"), 119 BuiltinTypeInfo("QSizeF", 22, "QSizeF"), 120 BuiltinTypeInfo("QLine", 23, "QLine"), 121 BuiltinTypeInfo("QLineF", 24, "QLineF"), 122 BuiltinTypeInfo("QPoint", 25, "QPoint"), 123 BuiltinTypeInfo("QPointF", 26, "QPointF"), 124 ] ~ easingCurveTypes ~ [ 125 BuiltinTypeInfo("QUuid", 30, "QUuid"), 126 BuiltinTypeInfo("QVariant", 41, "QVariant"), 127 ] ~ regularExpressionTypes ~ [ 128 BuiltinTypeInfo("QJsonValue", 45, "QJsonValue"), 129 BuiltinTypeInfo("QJsonObject", 46, "QJsonObject"), 130 BuiltinTypeInfo("QJsonArray", 47, "QJsonArray"), 131 BuiltinTypeInfo("QJsonDocument", 48, "QJsonDocument"), 132 BuiltinTypeInfo("QCborValue", 53, "QCborValue"), 133 BuiltinTypeInfo("QCborArray", 54, "QCborArray"), 134 BuiltinTypeInfo("QCborMap", 55, "QCborMap"), 135 ] ~ itemModelClasses; 136 137 enum immutable(BuiltinTypeInfo[]) corePointers = [ 138 BuiltinTypeInfo("QObjectStar", 39, "QObject*"), 139 ]; 140 141 enum immutable(BuiltinTypeInfo[]) coreTemplates = [ 142 BuiltinTypeInfo("QVariantMap", 8, "QVariantMap"), 143 BuiltinTypeInfo("QVariantList", 9, "QVariantList"), 144 BuiltinTypeInfo("QVariantHash", 28, "QVariantHash"), 145 BuiltinTypeInfo("QVariantPair", 58, "QVariantPair"), 146 BuiltinTypeInfo("QByteArrayList", 49, "QByteArrayList"), 147 BuiltinTypeInfo("QStringList", 11, "QStringList"), 148 ]; 149 150 /+ #if QT_CONFIG(shortcut) +/ 151 enum immutable(BuiltinTypeInfo[]) keySequenceClasses = [ 152 BuiltinTypeInfo("QKeySequence", 0x100b, "QKeySequence"), 153 ]; 154 /+ #else 155 #define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) 156 #endif +/ 157 158 enum immutable(BuiltinTypeInfo[]) guiClasses = [ 159 BuiltinTypeInfo("QFont", 0x1000, "QFont"), 160 BuiltinTypeInfo("QPixmap", 0x1001, "QPixmap"), 161 BuiltinTypeInfo("QBrush", 0x1002, "QBrush"), 162 BuiltinTypeInfo("QColor", 0x1003, "QColor"), 163 BuiltinTypeInfo("QPalette", 0x1004, "QPalette"), 164 BuiltinTypeInfo("QIcon", 0x1005, "QIcon"), 165 BuiltinTypeInfo("QImage", 0x1006, "QImage"), 166 BuiltinTypeInfo("QPolygon", 0x1007, "QPolygon"), 167 BuiltinTypeInfo("QRegion", 0x1008, "QRegion"), 168 BuiltinTypeInfo("QBitmap", 0x1009, "QBitmap"), 169 BuiltinTypeInfo("QCursor", 0x100a, "QCursor"), 170 ] ~ keySequenceClasses ~ [ 171 BuiltinTypeInfo("QPen", 0x100c, "QPen"), 172 BuiltinTypeInfo("QTextLength", 0x100d, "QTextLength"), 173 BuiltinTypeInfo("QTextFormat", 0x100e, "QTextFormat"), 174 BuiltinTypeInfo("QTransform", 0x1010, "QTransform"), 175 BuiltinTypeInfo("QMatrix4x4", 0x1011, "QMatrix4x4"), 176 BuiltinTypeInfo("QVector2D", 0x1012, "QVector2D"), 177 BuiltinTypeInfo("QVector3D", 0x1013, "QVector3D"), 178 BuiltinTypeInfo("QVector4D", 0x1014, "QVector4D"), 179 BuiltinTypeInfo("QQuaternion", 0x1015, "QQuaternion"), 180 BuiltinTypeInfo("QPolygonF", 0x1016, "QPolygonF"), 181 BuiltinTypeInfo("QColorSpace", 0x1017, "QColorSpace"), 182 ]; 183 184 185 enum immutable(BuiltinTypeInfo[]) widgetClasses = [ 186 BuiltinTypeInfo("QSizePolicy", 0x2000, "QSizePolicy"), 187 ]; 188 189 /+ 190 // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType") 191 #define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\ 192 F(ULong, -1, ulong, "unsigned long") \ 193 F(UInt, -1, uint, "unsigned int") \ 194 F(UShort, -1, ushort, "unsigned short") \ 195 F(UChar, -1, uchar, "unsigned char") \ 196 F(LongLong, -1, qlonglong, "long long") \ 197 F(ULongLong, -1, qulonglong, "unsigned long long") \ 198 F(SChar, -1, signed char, "qint8") \ 199 F(UChar, -1, uchar, "quint8") \ 200 F(Short, -1, short, "qint16") \ 201 F(UShort, -1, ushort, "quint16") \ 202 F(Int, -1, int, "qint32") \ 203 F(UInt, -1, uint, "quint32") \ 204 F(LongLong, -1, qlonglong, "qint64") \ 205 F(ULongLong, -1, qulonglong, "quint64") \ 206 F(QVariantList, -1, QVariantList, "QList<QVariant>") \ 207 F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \ 208 F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \ 209 F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \ 210 F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \ 211 F(QStringList, -1, QStringList, "QList<QString>") \ 212 +/ 213 214 enum immutable(BuiltinTypeInfo[]) allBuiltinTypes = 215 primitiveTypes 216 ~ primitivePointerTypes 217 ~ coreClasses 218 ~ corePointers 219 ~ coreTemplates 220 ~ guiClasses 221 ~ widgetClasses; 222 223 /+ 224 #define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \ 225 TypeName = Id, 226 227 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ 228 F(QList) \ 229 F(QQueue) \ 230 F(QStack) \ 231 F(QSet) \ 232 /*end*/ 233 234 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \ 235 F(QHash, class) \ 236 F(QMap, class) 237 238 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \ 239 F(QSharedPointer) \ 240 F(QWeakPointer) \ 241 F(QPointer) +/ 242 243 extern(C++, "QtPrivate") 244 { 245 246 247 extern(C++, class) struct QDebug; 248 extern(C++, class) struct QMetaTypeInterface 249 { 250 public: 251 ushort revision; // 0 in Qt 6.0. Can increase if new field are added 252 ushort alignment; 253 uint size; 254 uint flags; 255 /+ mutable +/ QBasicAtomicInt typeId; 256 257 alias MetaObjectFn = ExternCPPFunc!(const(QMetaObject)* function(const(QMetaTypeInterface)* )); 258 MetaObjectFn metaObjectFn; 259 260 const(char)* name; 261 262 alias DefaultCtrFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , void* )); 263 DefaultCtrFn defaultCtr; 264 alias CopyCtrFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , void* , const(void)* )); 265 CopyCtrFn copyCtr; 266 alias MoveCtrFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , void* , void* )); 267 MoveCtrFn moveCtr; 268 alias DtorFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , void* )); 269 DtorFn dtor; 270 alias EqualsFn = ExternCPPFunc!(bool function(const(QMetaTypeInterface)* , const(void)* , const(void)* )); 271 EqualsFn equals; 272 alias LessThanFn = ExternCPPFunc!(bool function(const(QMetaTypeInterface)* , const(void)* , const(void)* )); 273 LessThanFn lessThan; 274 alias DebugStreamFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , ref QDebug , const(void)* )); 275 DebugStreamFn debugStream; 276 alias DataStreamOutFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , ref QDataStream , const(void)* )); 277 DataStreamOutFn dataStreamOut; 278 alias DataStreamInFn = ExternCPPFunc!(void function(const(QMetaTypeInterface)* , ref QDataStream , void* )); 279 DataStreamInFn dataStreamIn; 280 281 alias LegacyRegisterOp = ExternCPPFunc!(void function()); 282 LegacyRegisterOp legacyRegisterOp; 283 } 284 285 /*! 286 This template is used for implicit conversion from type From to type To. 287 \internal 288 */ 289 To convertImplicit(From, To)(ref const(From) from) 290 { 291 return from; 292 } 293 294 /+ template<typename T, bool> 295 struct AssociativeValueTypeIsMetaType; 296 template<typename T, bool> 297 struct IsMetaTypePair; 298 template<typename, typename> 299 struct MetaTypeSmartPointerHelper; +/ 300 301 struct IsQFlags(T) { 302 /+ std:: +/false_type base0; 303 alias base0 this; 304 } 305 306 /+ template<typename Enum> 307 struct IsQFlags<QFlags<Enum>> : std::true_type {}; +/ 308 309 struct IsEnumOrFlags(T) { 310 /+ std:: +/disjunction!(/+ std:: +/is_enum!(T), IsQFlags!(T)) base0; 311 alias base0 this; 312 } 313 } // namespace QtPrivate 314 315 /// Binding for C++ class [QMetaType](https://doc.qt.io/qt-6/qmetatype.html). 316 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QMetaType { 317 public: 318 /+ #ifndef Q_CLANG_QDOC +/ 319 // The code that actually gets compiled. 320 mixin((){ 321 import std.conv; 322 string code = "enum Type {"; 323 // these are merged with QVariant 324 /+ QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID) +/ 325 foreach(t; allBuiltinTypes) 326 code ~= text(t.typeName, " = ", t.typeNameID, ", "); 327 code ~= q{ 328 FirstCoreType = Type.Bool, 329 LastCoreType = Type.QVariantPair, 330 FirstGuiType = Type.QFont, 331 LastGuiType = Type.QColorSpace, 332 FirstWidgetsType = Type.QSizePolicy, 333 LastWidgetsType = Type.QSizePolicy, 334 HighestInternalId = Type.LastWidgetsType, 335 336 QReal = qreal.sizeof == double.sizeof ? Type.Double : Type.Float, 337 338 UnknownType = 0, 339 User = 65536 340 }; 341 code ~= "}"; 342 return code; 343 }()); 344 /+ #else 345 // If we are using QDoc it fakes the Type enum looks like this. 346 enum Type { 347 UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5, 348 Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36, 349 UChar = 37, Float = 38, 350 VoidStar = 31, 351 QChar = 7, QString = 10, QStringList = 11, QByteArray = 12, 352 QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17, 353 QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22, 354 QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, 355 QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42, 356 QPersistentModelIndex = 50, QRegularExpression = 44, 357 QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48, 358 QByteArrayList = 49, QObjectStar = 39, SChar = 40, 359 Void = 43, 360 Nullptr = 51, 361 QVariantMap = 8, QVariantList = 9, QVariantHash = 28, 362 QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55, 363 Char16 = 56, Char32 = 57, 364 365 // Gui types 366 QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004, 367 QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009, 368 QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e, 369 QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012, 370 QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017, 371 372 // Widget types 373 QSizePolicy = 0x2000, 374 LastCoreType = Char32, 375 LastGuiType = QColorSpace, 376 User = 65536 377 }; 378 #endif +/ 379 380 enum TypeFlag { 381 NeedsConstruction = 0x1, 382 NeedsDestruction = 0x2, 383 RelocatableType = 0x4, 384 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 385 MovableType /+ Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") +/ = TypeFlag.RelocatableType, 386 /+ #endif +/ 387 PointerToQObject = 0x8, 388 IsEnumeration = 0x10, 389 SharedPointerToQObject = 0x20, 390 WeakPointerToQObject = 0x40, 391 TrackingPointerToQObject = 0x80, 392 IsUnsignedEnumeration = 0x100, 393 IsGadget = 0x200, 394 PointerToGadget = 0x400, 395 IsPointer = 0x800, 396 IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T> 397 IsConst = 0x2000, 398 } 399 /+ Q_DECLARE_FLAGS(TypeFlags, TypeFlag) +/ 400 alias TypeFlags = QFlags!(TypeFlag); 401 /+ static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type); +/ 402 403 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 404 /+ QT_DEPRECATED_VERSION_6_0 +/ 405 /+ static int type(const(char)* typeName) 406 { return QMetaType.fromName(QByteArrayView(typeName)).id(); } 407 /+ QT_DEPRECATED_VERSION_6_0 +/ 408 static int type(/+ QT_PREPEND_NAMESPACE(QByteArray) +/ ref const(QByteArray) typeName) 409 { return QMetaType.fromName(QByteArrayView(typeName)).id(); } 410 /+ QT_DEPRECATED_VERSION_6_0 +/ 411 static const(char)* typeName(int type) 412 { return QMetaType(type).name(); } 413 /+ QT_DEPRECATED_VERSION_6_0 +/ 414 static int sizeOf(int type) 415 { return cast(int)QMetaType(type).sizeOf(); } 416 /+ QT_DEPRECATED_VERSION_6_0 +/ 417 static TypeFlags typeFlags(int type) 418 { return QMetaType(type).flags(); } 419 /+ QT_DEPRECATED_VERSION_6_0 +/ 420 static const(QMetaObject)* metaObjectForType(int type) 421 { return QMetaType(type).metaObject(); } 422 /+ QT_DEPRECATED_VERSION_6_0 423 static void *create(int type, const void *copy = nullptr) 424 { return QMetaType(type).create(copy); } +/ 425 /+ QT_DEPRECATED_VERSION_6_0 +/ 426 static void destroy(int type, void* data) 427 { return QMetaType(type).destroy(data); } 428 /+ QT_DEPRECATED_VERSION_6_0 +/ 429 static void* construct(int type, void* where, const(void)* copy) 430 { return QMetaType(type).construct(where, copy); } 431 /+ QT_DEPRECATED_VERSION_6_0 +/ 432 static void destruct(int type, void* where) 433 { return QMetaType(type).destruct(where); }+/ 434 /+ #endif +/ 435 static bool isRegistered(int type); 436 437 /+ explicit +/this(int type); 438 /+ explicit +/ this(const(/+ QtPrivate:: +/QMetaTypeInterface)* d) 439 { 440 this.d_ptr = d; 441 } 442 /+ constexpr QMetaType() = default; +/ 443 444 bool isValid() const; 445 bool isRegistered() const; 446 static if(defined!"QT_QMETATYPE_BC_COMPAT") 447 { 448 int id() const; 449 } 450 else 451 { 452 // ### Qt 7: Remove traces of out of line version 453 // unused int parameter is used to avoid ODR violation 454 int id(int = 0) const 455 { 456 if (d_ptr) { 457 if (int id = d_ptr.typeId.loadRelaxed()) 458 return id; 459 return idHelper(); 460 } 461 return 0; 462 }/+ ; +/ 463 } 464 qsizetype sizeOf() const 465 { 466 return d_ptr ? d_ptr.size : 0; 467 } 468 qsizetype alignOf() const 469 { 470 return d_ptr ? d_ptr.alignment : 0; 471 } 472 TypeFlags flags() const 473 { 474 return d_ptr ? TypeFlags(cast(QFlag)(d_ptr.flags)) : TypeFlags(); 475 } 476 const(QMetaObject)* metaObject() const 477 { 478 return d_ptr && d_ptr.metaObjectFn ? d_ptr.metaObjectFn(d_ptr) : null; 479 } 480 const(char)* name() const 481 { 482 return d_ptr ? d_ptr.name : null; 483 } 484 485 /+ void *create(const void *copy = nullptr) const; +/ 486 void destroy(void* data) const; 487 void* construct(void* where, const(void)* copy = null) const; 488 void destruct(void* data) const; 489 QPartialOrdering compare(const(void)* lhs, const(void)* rhs) const; 490 bool equals(const(void)* lhs, const(void)* rhs) const; 491 492 bool isEqualityComparable() const; 493 bool isOrdered() const; 494 495 /+ #ifndef QT_NO_DATASTREAM +/ 496 version(QT_NO_DATASTREAM){}else 497 { 498 bool save(ref QDataStream stream, const(void)* data) const; 499 bool load(ref QDataStream stream, void* data) const; 500 bool hasRegisteredDataStreamOperators() const; 501 502 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 503 /+ QT_DEPRECATED_VERSION_6_0 +/ 504 static bool save(ref QDataStream stream, int type, const(void)* data) 505 { return QMetaType(type).save(stream, data); } 506 /+ QT_DEPRECATED_VERSION_6_0 +/ 507 static bool load(ref QDataStream stream, int type, void* data) 508 { return QMetaType(type).load(stream, data); } 509 } 510 /+ #endif 511 #endif +/ 512 513 static QMetaType fromType(T)() 514 { 515 return QMetaType(qMetaTypeInterfaceForType!(T)()); 516 } 517 static QMetaType fromName(QByteArrayView name); 518 519 /+ friend bool operator==(QMetaType a, QMetaType b) 520 { 521 if (a.d_ptr == b.d_ptr) 522 return true; 523 if (!a.d_ptr || !b.d_ptr) 524 return false; // one type is undefined, the other is defined 525 // avoid id call if we already have the id 526 const int aId = a.id(); 527 const int bId = b.id(); 528 return aId == bId; 529 } +/ 530 /+ friend bool operator!=(QMetaType a, QMetaType b) { return !(a == b); } +/ 531 532 public: 533 534 /+ #ifndef QT_NO_DEBUG_STREAM 535 bool debugStream(QDebug& dbg, const void *rhs); 536 bool hasRegisteredDebugStreamOperator() const; 537 538 #if QT_DEPRECATED_SINCE(6, 0) 539 QT_DEPRECATED_VERSION_6_0 540 static bool debugStream(QDebug& dbg, const void *rhs, int typeId) 541 { return QMetaType(typeId).debugStream(dbg, rhs); } 542 template<typename T> 543 QT_DEPRECATED_VERSION_6_0 544 static bool hasRegisteredDebugStreamOperator() 545 { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); } 546 QT_DEPRECATED_VERSION_6_0 547 static bool hasRegisteredDebugStreamOperator(int typeId) 548 { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); } 549 #endif 550 #endif +/ 551 552 // type erased converter function 553 // alias ConverterFunction = /+ std:: +/function_!(ExternCPPFunc!(bool function(const(void)* src, void* target))); 554 555 // type erased mutable view, primarily for containers 556 // alias MutableViewFunction = /+ std:: +/function_!(ExternCPPFunc!(bool function(void* src, void* target))); 557 558 // implicit conversion supported like double -> float 559 /+ template<typename From, typename To> +/ 560 /+ static bool registerConverter() 561 { 562 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>); 563 } +/ 564 565 // member function as in "QString QFont::toString() const" 566 /+ template<typename From, typename To> +/ 567 /+ static bool registerConverter(To(From::*function)() const) 568 { 569 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), 570 "QMetaType::registerConverter: At least one of the types must be a custom type."); 571 572 const QMetaType fromType = QMetaType::fromType<From>(); 573 const QMetaType toType = QMetaType::fromType<To>(); 574 auto converter = [function](const void *from, void *to) -> bool { 575 const From *f = static_cast<const From *>(from); 576 To *t = static_cast<To *>(to); 577 *t = (f->*function)(); 578 return true; 579 }; 580 return registerConverterImpl<From, To>(converter, fromType, toType); 581 } +/ 582 583 // member function 584 /+ template<typename From, typename To> +/ 585 /+ static bool registerMutableView(From,To)(ExternCPPFunc!(To function())/+ From::* +/ function_) 586 { 587 static assert((!QMetaTypeId2!(To).IsBuiltIn || !QMetaTypeId2!(From).IsBuiltIn), 588 "QMetaType::registerMutableView: At least one of the types must be a custom type."); 589 590 const(QMetaType) fromType = QMetaType.fromType!(From)(); 591 const(QMetaType) toType = QMetaType.fromType!(To)(); 592 auto view = [function](void *from, void *to) -> bool { 593 From* f = static_cast!(From*)(from); 594 To* t = static_cast!(To*)(to); 595 *t = (f->*function_)(); 596 return true; 597 }; 598 return registerMutableViewImpl!(From, To)(view, fromType, toType); 599 } +/ 600 601 // member function as in "double QString::toDouble(bool *ok = nullptr) const" 602 /+ template<typename From, typename To> +/ 603 /+ static bool registerConverter(To(From::*function)(bool*) const) 604 { 605 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), 606 "QMetaType::registerConverter: At least one of the types must be a custom type."); 607 608 const QMetaType fromType = QMetaType::fromType<From>(); 609 const QMetaType toType = QMetaType::fromType<To>(); 610 auto converter = [function](const void *from, void *to) -> bool { 611 const From *f = static_cast<const From *>(from); 612 To *t = static_cast<To *>(to); 613 bool result = true; 614 *t = (f->*function)(&result); 615 if (!result) 616 *t = To(); 617 return result; 618 }; 619 return registerConverterImpl<From, To>(converter, fromType, toType); 620 } +/ 621 622 // functor or function pointer 623 /+ template<typename From, typename To, typename UnaryFunction> +/ 624 /+ static bool registerConverter(UnaryFunction function) 625 { 626 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), 627 "QMetaType::registerConverter: At least one of the types must be a custom type."); 628 629 const QMetaType fromType = QMetaType::fromType<From>(); 630 const QMetaType toType = QMetaType::fromType<To>(); 631 auto converter = [function = std::move(function)](const void *from, void *to) -> bool { 632 const From *f = static_cast<const From *>(from); 633 To *t = static_cast<To *>(to); 634 *t = function(*f); 635 return true; 636 }; 637 return registerConverterImpl<From, To>(std::move(converter), fromType, toType); 638 } +/ 639 640 // functor or function pointer 641 /+ template<typename From, typename To, typename UnaryFunction> +/ 642 /+ static bool registerMutableView(From,To,UnaryFunction)(UnaryFunction function_) 643 { 644 static assert((!QMetaTypeId2!(To).IsBuiltIn || !QMetaTypeId2!(From).IsBuiltIn), 645 "QMetaType::registerMutableView: At least one of the types must be a custom type."); 646 647 const(QMetaType) fromType = QMetaType.fromType!(From)(); 648 const(QMetaType) toType = QMetaType.fromType!(To)(); 649 auto view = [function = /+ std:: +/move(function_)](void *from, void *to) -> bool { 650 From* f = static_cast!(From*)(from); 651 To* t = static_cast!(To*)(to); 652 *t = function_(*f); 653 return true; 654 }; 655 return registerMutableViewImpl!(From, To)(/+ std:: +/move(cast(_Tp && )(view)), fromType, toType); 656 } +/ 657 658 private: 659 /+ template<typename From, typename To> +/ 660 /+ static bool registerConverterImpl(From,To)(ConverterFunction converter, QMetaType fromType, QMetaType toType) 661 { 662 if (registerConverterFunction(/+ std:: +/move(converter), fromType, toType)) { 663 extern(D) static __gshared const unregister = qScopeGuard([=] { 664 unregisterConverterFunction(fromType, toType); 665 }); 666 return true; 667 } else { 668 return false; 669 } 670 } +/ 671 672 /+ template<typename From, typename To> +/ 673 /+ static bool registerMutableViewImpl(From,To)(MutableViewFunction view, QMetaType fromType, QMetaType toType) 674 { 675 if (registerMutableViewFunction(/+ std:: +/move(view), fromType, toType)) { 676 extern(D) static __gshared const unregister = qScopeGuard([=] { 677 unregisterMutableViewFunction(fromType, toType); 678 }); 679 return true; 680 } else { 681 return false; 682 } 683 } +/ 684 public: 685 686 static bool convert(QMetaType fromType, const(void)* from, QMetaType toType, void* to); 687 static bool canConvert(QMetaType fromType, QMetaType toType); 688 689 static bool view(QMetaType fromType, void* from, QMetaType toType, void* to); 690 static bool canView(QMetaType fromType, QMetaType toType); 691 /+ #if QT_DEPRECATED_SINCE(6, 0) +/ 692 /+ QT_DEPRECATED_VERSION_6_0 +/ 693 static bool convert(const(void)* from, int fromTypeId, void* to, int toTypeId) 694 { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); } 695 /+ QT_DEPRECATED_VERSION_6_0 +/ 696 static bool compare(const(void)* lhs, const(void)* rhs, int typeId, int* result) 697 { 698 auto t = QMetaType(typeId); 699 auto c = t.compare(lhs, rhs); 700 if (c == QPartialOrdering.Unordered) { 701 *result = 0; 702 return false; 703 } else if (c == QPartialOrdering.Less) { 704 *result = -1; 705 return true; 706 } else if (c == QPartialOrdering.Equivalent) { 707 *result = 0; 708 return true; 709 } else { 710 *result = 1; 711 return true; 712 } 713 } 714 /+ QT_DEPRECATED_VERSION_6_0 +/ 715 static bool equals(const(void)* lhs, const(void)* rhs, int typeId, int* result) 716 { 717 auto t = QMetaType(typeId); 718 if (!t.isEqualityComparable()) 719 return false; 720 *result = t.equals(lhs, rhs) ? 0 : -1; 721 return true; 722 } 723 /+ #endif +/ 724 725 /+ template<typename From, typename To> +/ 726 /+ static bool hasRegisteredConverterFunction() 727 { 728 return hasRegisteredConverterFunction( 729 QMetaType::fromType<From>(), QMetaType::fromType<To>()); 730 } +/ 731 732 /+ static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType); +/ 733 734 /+ template<typename From, typename To> +/ 735 static bool hasRegisteredMutableViewFunction(From,To)() 736 { 737 return hasRegisteredMutableViewFunction( 738 QMetaType.fromType!(From)(), QMetaType.fromType!(To)()); 739 } 740 741 static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType); 742 743 /+ #ifndef Q_CLANG_QDOC +/ 744 /+ template<typename, bool> +/ /+ friend struct QtPrivate::SequentialValueTypeIsMetaType; +/ 745 /+ template<typename, bool> +/ /+ friend struct QtPrivate::AssociativeValueTypeIsMetaType; +/ 746 /+ template<typename, bool> +/ /+ friend struct QtPrivate::IsMetaTypePair; +/ 747 /+ template<typename, typename> +/ /+ friend struct QtPrivate::MetaTypeSmartPointerHelper; +/ 748 /+ #endif +/ 749 // static bool registerConverterFunction(ref const(ConverterFunction) f, QMetaType from, QMetaType to); 750 // static void unregisterConverterFunction(QMetaType from, QMetaType to); 751 752 // static bool registerMutableViewFunction(ref const(MutableViewFunction) f, QMetaType from, QMetaType to); 753 // static void unregisterMutableViewFunction(QMetaType from, QMetaType to); 754 755 static void unregisterMetaType(QMetaType type); 756 const(/+ QtPrivate:: +/QMetaTypeInterface)* iface() { return d_ptr; } 757 758 package: 759 mixin(changeWindowsMangling(q{mangleChangeAccess("private")}, q{ 760 int idHelper() const; 761 })); 762 /+ friend class QVariant; +/ 763 const(/+ QtPrivate:: +/QMetaTypeInterface)* d_ptr = null; 764 mixin(CREATE_CONVENIENCE_WRAPPERS); 765 } 766 767 /+ #undef QT_DEFINE_METATYPE_ID +/ 768 /+pragma(inline, true) QFlags!(QMetaType.TypeFlags.enum_type) operator |(QMetaType.TypeFlags.enum_type f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/{return QFlags!(QMetaType.TypeFlags.enum_type)(f1)|f2;}+/ 769 /+pragma(inline, true) QFlags!(QMetaType.TypeFlags.enum_type) operator |(QMetaType.TypeFlags.enum_type f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/{return f2|f1;}+/ 770 /+pragma(inline, true) QFlags!(QMetaType.TypeFlags.enum_type) operator &(QMetaType.TypeFlags.enum_type f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/{return QFlags!(QMetaType.TypeFlags.enum_type)(f1)&f2;}+/ 771 /+pragma(inline, true) QFlags!(QMetaType.TypeFlags.enum_type) operator &(QMetaType.TypeFlags.enum_type f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/{return f2&f1;}+/ 772 /+pragma(inline, true) void operator +(QMetaType.TypeFlags.enum_type f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/;+/ 773 /+pragma(inline, true) void operator +(QMetaType.TypeFlags.enum_type f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/;+/ 774 /+pragma(inline, true) void operator +(int f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/;+/ 775 /+pragma(inline, true) void operator -(QMetaType.TypeFlags.enum_type f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/;+/ 776 /+pragma(inline, true) void operator -(QMetaType.TypeFlags.enum_type f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/;+/ 777 /+pragma(inline, true) void operator -(int f1, QFlags!(QMetaType.TypeFlags.enum_type) f2)/+noexcept+/;+/ 778 /+pragma(inline, true) QIncompatibleFlag operator |(QMetaType.TypeFlags.enum_type f1, int f2)/+noexcept+/{return QIncompatibleFlag(int(f1)|f2);}+/ 779 /+pragma(inline, true) void operator +(int f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/;+/ 780 /+pragma(inline, true) void operator +(QMetaType.TypeFlags.enum_type f1, int f2)/+noexcept+/;+/ 781 /+pragma(inline, true) void operator -(int f1, QMetaType.TypeFlags.enum_type f2)/+noexcept+/;+/ 782 /+pragma(inline, true) void operator -(QMetaType.TypeFlags.enum_type f1, int f2)/+noexcept+/;+/ 783 784 /+ Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags) 785 #define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \ 786 } \ 787 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \ 788 namespace QtMetaTypePrivate { 789 790 791 namespace QtMetaTypePrivate { 792 793 794 class QPairVariantInterfaceImpl 795 { 796 public: 797 const void *_pair; 798 QMetaType _metaType_first; 799 QMetaType _metaType_second; 800 801 typedef void (*getFunc)(const void * const *p, void *); 802 803 getFunc _getFirst; 804 getFunc _getSecond; 805 806 template<class T> 807 static void getFirstImpl(const void * const *pair, void *dataPtr) 808 { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; } 809 template<class T> 810 static void getSecondImpl(const void * const *pair, void *dataPtr) 811 { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; } 812 813 public: 814 template<class T> QPairVariantInterfaceImpl(const T*p) 815 : _pair(p) 816 , _metaType_first(QMetaType::fromType<typename T::first_type>()) 817 , _metaType_second(QMetaType::fromType<typename T::second_type>()) 818 , _getFirst(getFirstImpl<T>) 819 , _getSecond(getSecondImpl<T>) 820 { 821 } 822 823 constexpr QPairVariantInterfaceImpl() 824 : _pair(nullptr) 825 , _getFirst(nullptr) 826 , _getSecond(nullptr) 827 { 828 } 829 830 inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); } 831 inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); } 832 }; 833 QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_RELOCATABLE_TYPE) 834 template<typename From> 835 struct QPairVariantInterfaceConvertFunctor; 836 837 template<typename T, typename U> 838 struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> > 839 { 840 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const 841 ==== BASE ==== 842 { 843 return QPairVariantInterfaceImpl(&f); 844 } 845 }; 846 847 } 848 849 850 #define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \ 851 template <class T> class Name; \ 852 853 854 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER) +/ 855 extern(C++, "QtPrivate") 856 { 857 struct IsPointerToTypeDerivedFromQObject(T) 858 { 859 enum { Value = false } 860 } 861 862 // Specialize to avoid sizeof(void) warning 863 /+ template<> 864 struct IsPointerToTypeDerivedFromQObject<void*> 865 { 866 enum { Value = false }; 867 }; 868 template<> 869 struct IsPointerToTypeDerivedFromQObject<const void*> 870 { 871 enum { Value = false }; 872 }; 873 template<> 874 struct IsPointerToTypeDerivedFromQObject<QObject*> 875 { 876 enum { Value = true }; 877 }; 878 879 template<typename T> 880 struct IsPointerToTypeDerivedFromQObject<T*> 881 { 882 typedef qint8 yes_type; 883 typedef qint64 no_type; 884 885 #ifndef QT_NO_QOBJECT 886 static yes_type checkType(QObject* ); 887 static yes_type checkType(const QObject* ); 888 #endif 889 static no_type checkType(...); 890 static_assert(sizeof(T), "Type argument of Q_PROPERTY or Q_DECLARE_METATYPE(T*) must be fully defined"); 891 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) }; 892 }; +/ 893 894 struct IsGadgetHelper(T, Enable) { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false } } 895 896 /+ template<typename T> 897 struct IsGadgetHelper<T, typename T::QtGadgetHelper> 898 { 899 template <typename X> 900 static char checkType(void (X::*)()); 901 static void *checkType(void (T::*)()); 902 enum { 903 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *), 904 IsGadgetOrDerivedFrom = true 905 }; 906 }; +/ 907 908 struct IsPointerToGadgetHelper(T, Enable) { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false } } 909 910 /+ template<typename T> 911 struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper> 912 { 913 using BaseType = T; 914 template <typename X> 915 static char checkType(void (X::*)()); 916 static void *checkType(void (T::*)()); 917 enum { 918 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *), 919 IsGadgetOrDerivedFrom = !IsPointerToTypeDerivedFromQObject<T*>::Value 920 }; 921 }; 922 923 924 template<typename T> char qt_getEnumMetaObject(const T&); +/ 925 926 struct IsQEnumHelper(T) { 927 static ref const(T) declval(); 928 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the 929 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*. 930 // Otherwise the chosen overload will be the catch all template function 931 // qt_getEnumMetaObject(T) which returns 'char' 932 enum { Value = (qt_getEnumMetaObject(declval())). sizeof == (QMetaObject*).sizeof } 933 } 934 /+ template<> struct IsQEnumHelper<void> { enum { Value = false }; }; 935 936 template<typename T, typename Enable = void> 937 struct MetaObjectForType 938 { 939 static constexpr const QMetaObject *value() { return nullptr; } 940 using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *); 941 static constexpr MetaObjectFn metaObjectFunction = nullptr; 942 }; 943 #ifndef QT_NO_QOBJECT 944 template<> 945 struct MetaObjectForType<void> 946 { 947 static constexpr const QMetaObject *value() { return nullptr; } 948 using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *); 949 static constexpr MetaObjectFn metaObjectFunction = nullptr; 950 }; 951 template<typename T> 952 struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> 953 { 954 static constexpr const QMetaObject *value() { return &T::staticMetaObject; } 955 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; } 956 }; 957 template<typename T> 958 struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type> 959 { 960 static constexpr const QMetaObject *value() { return &T::staticMetaObject; } 961 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; } 962 }; 963 template<typename T> 964 struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type> 965 { 966 static constexpr const QMetaObject *value() 967 { 968 return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; 969 } 970 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); } 971 }; 972 template<typename T> 973 struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type > 974 { 975 static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); } 976 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); } 977 }; 978 #endif +/ 979 template MetaObjectForType(T) 980 { 981 static if(is(const(T): const(QObject))) 982 { 983 static const(QMetaObject)* value() { return &T.staticMetaObject; } 984 static const(QMetaObject)* metaObjectFunction(const(QMetaTypeInterface)*) { return &T.staticMetaObject; } 985 } 986 else 987 { 988 static const(QMetaObject)* value() { return null; } 989 alias MetaObjectFn = const(QMetaObject)* function(const(QMetaTypeInterface)*); 990 extern(D) static immutable MetaObjectFn metaObjectFunction = null; 991 } 992 } 993 994 struct IsSharedPointerToTypeDerivedFromQObject(T) 995 { 996 enum { Value = false } 997 } 998 999 /+ template<typename T> 1000 struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*> 1001 { 1002 }; +/ 1003 1004 struct IsWeakPointerToTypeDerivedFromQObject(T) 1005 { 1006 enum { Value = false } 1007 } 1008 1009 /+ template<typename T> 1010 struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*> 1011 { 1012 }; +/ 1013 1014 struct IsTrackingPointerToTypeDerivedFromQObject(T) 1015 { 1016 enum { Value = false } 1017 } 1018 1019 /+ template<typename T> 1020 struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> > 1021 { 1022 enum { Value = true }; 1023 }; 1024 1025 template<typename T> 1026 struct IsSequentialContainer 1027 { 1028 enum { Value = false }; 1029 }; 1030 1031 template<typename T> 1032 struct IsAssociativeContainer 1033 { 1034 enum { Value = false }; 1035 }; +/ 1036 1037 struct SequentialContainerTransformationHelper(T, /+ bool +/ /+ = QtPrivate::IsSequentialContainer<T>::Value +/) 1038 { 1039 /+ static bool registerConverter() 1040 { 1041 return false; 1042 } +/ 1043 1044 static bool registerMutableView() 1045 { 1046 return false; 1047 } 1048 } 1049 1050 struct SequentialValueTypeIsMetaType(T, /+ bool +/ /+ = QMetaTypeId2<typename T::value_type>::Defined +/) 1051 { 1052 /+ static bool registerConverter() 1053 { 1054 return false; 1055 } +/ 1056 1057 static bool registerMutableView() 1058 { 1059 return false; 1060 } 1061 } 1062 1063 /+ template<typename T> 1064 struct SequentialContainerTransformationHelper<T, true> : SequentialValueTypeIsMetaType<T> 1065 { 1066 }; +/ 1067 1068 struct AssociativeContainerTransformationHelper(T, /+ bool +/ /+ = QtPrivate::IsAssociativeContainer<T>::Value +/) 1069 { 1070 /+ static bool registerConverter() 1071 { 1072 return false; 1073 } +/ 1074 1075 static bool registerMutableView() 1076 { 1077 return false; 1078 } 1079 } 1080 1081 struct AssociativeKeyTypeIsMetaType(T, /+ bool +/ /+ = QMetaTypeId2<typename T::key_type>::Defined +/) 1082 { 1083 /+ static bool registerConverter() 1084 { 1085 return false; 1086 } +/ 1087 1088 static bool registerMutableView() 1089 { 1090 return false; 1091 } 1092 } 1093 1094 struct AssociativeMappedTypeIsMetaType(T, /+ bool +/ /+ = QMetaTypeId2<typename T::mapped_type>::Defined +/) 1095 { 1096 /+ static bool registerConverter() 1097 { 1098 return false; 1099 } +/ 1100 1101 static bool registerMutableView() 1102 { 1103 return false; 1104 } 1105 } 1106 1107 /+ template<typename T> 1108 struct AssociativeContainerTransformationHelper<T, true> : AssociativeKeyTypeIsMetaType<T> 1109 { 1110 }; 1111 1112 template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined 1113 && QMetaTypeId2<typename T::second_type>::Defined> 1114 struct IsMetaTypePair 1115 { 1116 static bool registerConverter() 1117 { 1118 return false; 1119 } 1120 }; 1121 1122 template<typename T> 1123 struct IsMetaTypePair<T, true> 1124 { 1125 inline static bool registerConverter(); 1126 }; 1127 1128 template<typename T> 1129 struct IsPair 1130 { 1131 static bool registerConverter() 1132 { 1133 return false; 1134 } 1135 }; 1136 template<typename T, typename U> 1137 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {}; 1138 1139 template<typename T> 1140 struct MetaTypePairHelper : IsPair<T> {}; 1141 1142 template<typename T, typename = void> 1143 struct MetaTypeSmartPointerHelper 1144 { 1145 static bool registerConverter() { return false; } 1146 }; 1147 1148 Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type); +/ 1149 } // namespace QtPrivate 1150 1151 struct QMetaTypeIdQObject(T, /+ int +/ /+ = 1152 QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 1153 QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget : 1154 QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget : 1155 QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0 +/) 1156 { 1157 enum { 1158 Defined = 0 1159 } 1160 } 1161 1162 alias QMetaTypeId(T) = QMetaTypeIdQObject!(T); 1163 1164 mixin((){ 1165 import std.conv; 1166 string code = "template QMetaTypeId2(T)\n"; 1167 code ~= "{\n"; 1168 code ~= " static if(std.traits.isBuiltinType!T)\n"; 1169 code ~= " {\n"; 1170 bool needsElse = false; 1171 foreach(i, t; allBuiltinTypes) 1172 { 1173 string realType2 = t.realType; 1174 if(t.dType.length) 1175 realType2 = t.dType; 1176 if(realType2[0] != 'Q') 1177 { 1178 code ~= " "; 1179 if(needsElse) 1180 code ~= "else "; 1181 code ~= text("static if(is(T == ", realType2, "))\n"); 1182 code ~= " {\n"; 1183 code ~= text(" enum { Defined = 1, IsBuiltIn = true, MetaType = ", t.typeNameID, " };\n"); 1184 code ~= text(" pragma(inline, true) static int qt_metatype_id() { return ", t.typeNameID, "; }\n"); 1185 code ~= text(" extern(D) static immutable(char[", t.realType.length, " + 1]) nameAsArray = \"", t.realType, "\";\n"); 1186 code ~= " }\n"; 1187 needsElse = true; 1188 } 1189 } 1190 code ~= " else\n"; 1191 code ~= " {\n"; 1192 code ~= " static assert(false, \"type not supported \" ~ T.stringof);\n"; 1193 code ~= " }\n"; 1194 code ~= " }\n"; 1195 code ~= " else\n"; 1196 code ~= " {\n"; 1197 needsElse = false; 1198 code ~= " static if(IsInQtPackage!T)\n"; 1199 code ~= " {\n"; 1200 foreach(i, t; allBuiltinTypes) 1201 { 1202 string realType2 = t.realType; 1203 if(t.dType.length) 1204 realType2 = t.dType; 1205 if(realType2[0] == 'Q') 1206 { 1207 code ~= " "; 1208 if(needsElse) 1209 code ~= "else "; 1210 // TODO: Match templates like QList!(QString) 1211 code ~= text("static if(__traits(identifier, T) == \"", realType2, "\")\n"); 1212 code ~= " {\n"; 1213 code ~= text(" enum { Defined = 1, IsBuiltIn = true, MetaType = ", t.typeNameID, " };\n"); 1214 code ~= text(" pragma(inline, true) static int qt_metatype_id() { return ", t.typeNameID, "; }\n"); 1215 code ~= text(" extern(D) static immutable(char[", t.realType.length, " + 1]) nameAsArray = \"", t.realType, "\";\n"); 1216 code ~= " }\n"; 1217 needsElse = true; 1218 } 1219 } 1220 code ~= " else\n"; 1221 code ~= " {\n"; 1222 code ~= " enum { Defined = QMetaTypeId!(T).Defined, IsBuiltIn=false }\n"; 1223 code ~= " pragma(inline, true) static int qt_metatype_id() { return QMetaTypeId!(T).qt_metatype_id(); }\n"; 1224 code ~= " }\n"; 1225 code ~= " }\n"; 1226 code ~= " else\n"; 1227 code ~= " {\n"; 1228 code ~= " enum { Defined = QMetaTypeId!(T).Defined, IsBuiltIn=false }\n"; 1229 code ~= " pragma(inline, true) static int qt_metatype_id() { return QMetaTypeId!(T).qt_metatype_id(); }\n"; 1230 code ~= " }\n"; 1231 code ~= " }\n"; 1232 code ~= "}\n"; 1233 return code; 1234 }()); 1235 1236 /+ template <typename T> 1237 struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {}; 1238 1239 template <typename T> 1240 struct QMetaTypeId2<T&> { enum {Defined = false }; }; +/ 1241 1242 extern(C++, "QtPrivate") { 1243 struct QMetaTypeIdHelper(T, bool Defined=QMetaTypeId2!(T).Defined) { 1244 pragma(inline, true) static int qt_metatype_id() 1245 { return QMetaTypeId2!(T).qt_metatype_id(); } 1246 } 1247 /+ template <typename T> struct QMetaTypeIdHelper<T, false> { 1248 static inline constexpr int qt_metatype_id() 1249 { return -1; } 1250 }; 1251 1252 // Function pointers don't derive from QObject 1253 template <typename Result, typename... Args> 1254 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; }; 1255 1256 template<typename T> 1257 inline constexpr bool IsQmlListType = false; 1258 1259 template<typename T, bool = std::is_enum<T>::value> 1260 constexpr bool IsUnsignedEnum = false; 1261 template<typename T> 1262 constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>; +/ 1263 1264 private template RemovePointer(T) 1265 { 1266 static if(is(T == X*, X)) 1267 alias RemovePointer = typeof(*T.init); 1268 else 1269 alias RemovePointer = T; 1270 } 1271 1272 struct QMetaTypeTypeFlags(T) 1273 { 1274 enum { Flags = (QTypeInfo!(T).isRelocatable ? QMetaType.TypeFlag.RelocatableType : 0) 1275 | (QTypeInfo!(T).isComplex ? QMetaType.TypeFlag.NeedsConstruction : 0) 1276 | (QTypeInfo!(T).isComplex ? QMetaType.TypeFlag.NeedsDestruction : 0) 1277 // TODO 1278 /*| (IsPointerToTypeDerivedFromQObject!(T).Value ? QMetaType.TypeFlag.PointerToQObject : 0) 1279 | (IsSharedPointerToTypeDerivedFromQObject!(T).Value ? QMetaType.TypeFlag.SharedPointerToQObject : 0) 1280 | (IsWeakPointerToTypeDerivedFromQObject!(T).Value ? QMetaType.TypeFlag.WeakPointerToQObject : 0) 1281 | (IsTrackingPointerToTypeDerivedFromQObject!(T).Value ? QMetaType.TypeFlag.TrackingPointerToQObject : 0) 1282 | (IsEnumOrFlags!(T).value ? QMetaType.TypeFlag.IsEnumeration : 0) 1283 | (IsGadgetHelper!(T).IsGadgetOrDerivedFrom ? QMetaType.TypeFlag.IsGadget : 0) 1284 | (IsPointerToGadgetHelper!(T).IsGadgetOrDerivedFrom ? QMetaType.TypeFlag.PointerToGadget : 0)*/ 1285 | (QTypeInfo!(T).isPointer ? QMetaType.TypeFlag.IsPointer : 0) 1286 //| (IsUnsignedEnum!(T) ? QMetaType.TypeFlag.IsUnsignedEnumeration : 0) 1287 //| (IsQmlListType!(T) ? QMetaType.TypeFlag.IsQmlList : 0) 1288 | (is(RemovePointer!(T) == const) ? QMetaType.TypeFlag.IsConst : 0) 1289 }; 1290 }; 1291 1292 struct MetaTypeDefinedHelper(T, bool defined) 1293 { 1294 enum DefinedType { Defined = defined } 1295 } 1296 1297 struct QSmartPointerConvertFunctor(SmartPointer) 1298 { 1299 /+QObject operator ()(ref const(SmartPointer) p) const 1300 { 1301 return p.operator->(); 1302 }+/ 1303 } 1304 1305 // hack to delay name lookup to instantiation time by making 1306 // EnableInternalData a dependent name: 1307 1308 /+ template<typename T> 1309 struct QSmartPointerConvertFunctor<QWeakPointer<T> > 1310 { 1311 QObject* operator()(const QWeakPointer<T> &p) const 1312 { 1313 return QtPrivate::EnableInternalDataWrap<T>::internalData(p); 1314 } 1315 }; +/ 1316 1317 } 1318 1319 /+ template <typename T> 1320 int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName) 1321 { 1322 #ifndef QT_NO_QOBJECT 1323 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), 1324 "qRegisterNormalizedMetaType", 1325 "qRegisterNormalizedMetaType was called with a not normalized type name, " 1326 "please call qRegisterMetaType instead."); 1327 #endif 1328 1329 const QMetaType metaType = QMetaType::fromType<T>(); 1330 const int id = metaType.id(); 1331 1332 QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter(); 1333 QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView(); 1334 QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter(); 1335 QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView(); 1336 QtPrivate::MetaTypePairHelper<T>::registerConverter(); 1337 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(); 1338 1339 if (normalizedTypeName != metaType.name()) 1340 QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType); 1341 1342 return id; 1343 } +/ 1344 1345 int qRegisterMetaType(T)(const(char)* typeName) 1346 { 1347 /+ #ifdef QT_NO_QOBJECT 1348 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName; 1349 #else +/ 1350 /+ QT_PREPEND_NAMESPACE(QByteArray) +/QByteArray normalizedTypeName = QMetaObject.normalizedType(typeName); 1351 /+ #endif +/ 1352 return qRegisterNormalizedMetaType!(T)(normalizedTypeName); 1353 } 1354 1355 pragma(inline, true) int qMetaTypeId(T)() 1356 { 1357 static if (cast(bool)(QMetaTypeId2!(T).IsBuiltIn)) { 1358 return QMetaTypeId2!(T).MetaType; 1359 } else { 1360 return QMetaType.fromType!(T)().id(); 1361 } 1362 } 1363 1364 pragma(inline, true) int qRegisterMetaType(T)() 1365 { 1366 int id = qMetaTypeId!(T)(); 1367 return id; 1368 } 1369 1370 /+ #ifndef QT_NO_QOBJECT 1371 template <typename T> 1372 struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject> 1373 { 1374 enum { 1375 Defined = 1 1376 }; 1377 1378 static int qt_metatype_id() 1379 { 1380 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); 1381 if (const int id = metatype_id.loadAcquire()) 1382 return id; 1383 const char *const cName = T::staticMetaObject.className(); 1384 QByteArray typeName; 1385 typeName.reserve(strlen(cName) + 1); 1386 typeName.append(cName).append('*'); 1387 const int newId = qRegisterNormalizedMetaType<T *>(typeName); 1388 metatype_id.storeRelease(newId); 1389 return newId; 1390 } 1391 }; 1392 1393 template <typename T> 1394 struct QMetaTypeIdQObject<T, QMetaType::IsGadget> 1395 { 1396 enum { 1397 Defined = std::is_default_constructible<T>::value 1398 }; 1399 1400 static int qt_metatype_id() 1401 { 1402 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); 1403 if (const int id = metatype_id.loadAcquire()) 1404 return id; 1405 const char *const cName = T::staticMetaObject.className(); 1406 const int newId = qRegisterNormalizedMetaType<T>(cName); 1407 metatype_id.storeRelease(newId); 1408 return newId; 1409 } 1410 }; 1411 1412 template <typename T> 1413 struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget> 1414 { 1415 enum { 1416 Defined = 1 1417 }; 1418 1419 static int qt_metatype_id() 1420 { 1421 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); 1422 if (const int id = metatype_id.loadAcquire()) 1423 return id; 1424 const char *const cName = T::staticMetaObject.className(); 1425 QByteArray typeName; 1426 typeName.reserve(strlen(cName) + 1); 1427 typeName.append(cName).append('*'); 1428 const int newId = qRegisterNormalizedMetaType<T *>(typeName); 1429 metatype_id.storeRelease(newId); 1430 return newId; 1431 } 1432 }; 1433 1434 template <typename T> 1435 struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration> 1436 { 1437 enum { 1438 Defined = 1 1439 }; 1440 1441 static int qt_metatype_id() 1442 { 1443 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); 1444 if (const int id = metatype_id.loadAcquire()) 1445 return id; 1446 const char *eName = qt_getEnumName(T()); 1447 const char *cName = qt_getEnumMetaObject(T())->className(); 1448 QByteArray typeName; 1449 typeName.reserve(strlen(cName) + 2 + strlen(eName)); 1450 typeName.append(cName).append("::").append(eName); 1451 const int newId = qRegisterNormalizedMetaType<T>(typeName); 1452 metatype_id.storeRelease(newId); 1453 return newId; 1454 } 1455 }; 1456 #endif 1457 1458 #define Q_DECLARE_OPAQUE_POINTER(POINTER) \ 1459 QT_BEGIN_NAMESPACE namespace QtPrivate { \ 1460 template <> \ 1461 struct IsPointerToTypeDerivedFromQObject<POINTER > \ 1462 { \ 1463 enum { Value = false }; \ 1464 }; \ 1465 } QT_END_NAMESPACE \ 1466 /**/ 1467 1468 #ifndef Q_MOC_RUN 1469 #define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE) 1470 #define Q_DECLARE_METATYPE_IMPL(TYPE) \ 1471 QT_BEGIN_NAMESPACE \ 1472 template <> \ 1473 struct QMetaTypeId< TYPE > \ 1474 { \ 1475 enum { Defined = 1 }; \ 1476 static int qt_metatype_id() \ 1477 { \ 1478 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ 1479 if (const int id = metatype_id.loadAcquire()) \ 1480 return id; \ 1481 constexpr auto arr = QtPrivate::typenameHelper<TYPE>(); \ 1482 auto name = arr.data(); \ 1483 if (QByteArrayView(name) == (#TYPE)) { \ 1484 const int id = qRegisterNormalizedMetaType<TYPE>(name); \ 1485 metatype_id.storeRelease(id); \ 1486 return id; \ 1487 } \ 1488 const int newId = qRegisterMetaType< TYPE >(#TYPE); \ 1489 metatype_id.storeRelease(newId); \ 1490 return newId; \ 1491 } \ 1492 }; \ 1493 QT_END_NAMESPACE 1494 #endif // Q_MOC_RUN 1495 1496 #define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \ 1497 QT_BEGIN_NAMESPACE \ 1498 template<> struct QMetaTypeId2<NAME> \ 1499 { \ 1500 using NameAsArrayType = std::array<char, sizeof(#NAME)>; \ 1501 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \ 1502 static inline constexpr int qt_metatype_id() { return METATYPEID; } \ 1503 static constexpr NameAsArrayType nameAsArray = { #NAME }; \ 1504 }; \ 1505 QT_END_NAMESPACE 1506 1507 #define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \ 1508 class Name; 1509 1510 1511 QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) +/ 1512 extern(C++, class) struct QMatrix4x4; 1513 extern(C++, class) struct QQuaternion; 1514 /+ QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) 1515 QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) 1516 #undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER 1517 1518 #define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \ 1519 QT_BEGIN_NAMESPACE \ 1520 template <typename T> \ 1521 struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \ 1522 { \ 1523 enum { \ 1524 Defined = QMetaTypeId2<T>::Defined \ 1525 }; \ 1526 static int qt_metatype_id() \ 1527 { \ 1528 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ 1529 if (const int id = metatype_id.loadRelaxed()) \ 1530 return id; \ 1531 const char *tName = QMetaType::fromType<T>().name(); \ 1532 Q_ASSERT(tName); \ 1533 const size_t tNameLen = qstrlen(tName); \ 1534 QByteArray typeName; \ 1535 typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1); \ 1536 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \ 1537 .append('<').append(tName, tNameLen); \ 1538 typeName.append('>'); \ 1539 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName); \ 1540 metatype_id.storeRelease(newId); \ 1541 return newId; \ 1542 } \ 1543 }; \ 1544 namespace QtPrivate { \ 1545 template<typename T> \ 1546 struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \ 1547 { \ 1548 enum { Value = true }; \ 1549 }; \ 1550 } \ 1551 QT_END_NAMESPACE 1552 1553 #define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \ 1554 QT_BEGIN_NAMESPACE \ 1555 template<typename T, typename U> \ 1556 struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \ 1557 { \ 1558 enum { \ 1559 Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \ 1560 }; \ 1561 static int qt_metatype_id() \ 1562 { \ 1563 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ 1564 if (const int id = metatype_id.loadAcquire()) \ 1565 return id; \ 1566 const char *tName = QMetaType::fromType<T>().name(); \ 1567 const char *uName = QMetaType::fromType<U>().name(); \ 1568 Q_ASSERT(tName); \ 1569 Q_ASSERT(uName); \ 1570 const size_t tNameLen = qstrlen(tName); \ 1571 const size_t uNameLen = qstrlen(uName); \ 1572 QByteArray typeName; \ 1573 typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \ 1574 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \ 1575 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \ 1576 typeName.append('>'); \ 1577 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName); \ 1578 metatype_id.storeRelease(newId); \ 1579 return newId; \ 1580 } \ 1581 }; \ 1582 QT_END_NAMESPACE 1583 1584 namespace QtPrivate { 1585 1586 template<typename T, bool /* isSharedPointerToQObjectDerived */ = false> 1587 struct SharedPointerMetaTypeIdHelper 1588 { 1589 enum { 1590 Defined = 0 1591 }; 1592 static int qt_metatype_id() 1593 { 1594 return -1; 1595 } 1596 }; 1597 1598 } 1599 1600 #define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \ 1601 QT_BEGIN_NAMESPACE \ 1602 namespace QtPrivate { \ 1603 template<typename T> \ 1604 struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \ 1605 { \ 1606 enum { \ 1607 Defined = 1 \ 1608 }; \ 1609 static int qt_metatype_id() \ 1610 { \ 1611 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ 1612 if (const int id = metatype_id.loadAcquire()) \ 1613 return id; \ 1614 const char * const cName = T::staticMetaObject.className(); \ 1615 QByteArray typeName; \ 1616 typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1); \ 1617 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \ 1618 .append('<').append(cName).append('>'); \ 1619 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName); \ 1620 metatype_id.storeRelease(newId); \ 1621 return newId; \ 1622 } \ 1623 }; \ 1624 template<typename T> \ 1625 struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \ 1626 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \ 1627 { \ 1628 static bool registerConverter() \ 1629 { \ 1630 const QMetaType to = QMetaType(QMetaType::QObjectStar); \ 1631 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) { \ 1632 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \ 1633 return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o); \ 1634 } \ 1635 return true; \ 1636 } \ 1637 }; \ 1638 } \ 1639 template <typename T> \ 1640 struct QMetaTypeId< SMART_POINTER<T> > \ 1641 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \ 1642 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \ 1643 { \ 1644 };\ 1645 QT_END_NAMESPACE 1646 1647 #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \ 1648 Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME) 1649 1650 1651 1652 QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER) 1653 #undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER 1654 1655 #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG 1656 1657 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector) 1658 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list) 1659 1660 #define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \ 1661 QT_BEGIN_NAMESPACE \ 1662 namespace QtPrivate { \ 1663 template<typename T, typename U> \ 1664 struct IsAssociativeContainer<TEMPLATENAME<T, U> > \ 1665 { \ 1666 enum { Value = true }; \ 1667 }; \ 1668 } \ 1669 QT_END_NAMESPACE \ 1670 Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME) 1671 1672 1673 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash) 1674 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap) 1675 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map) 1676 Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair) 1677 1678 #define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \ 1679 Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME) 1680 1681 1682 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER) 1683 1684 #undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER 1685 1686 1687 QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE) 1688 1689 1690 1691 template <typename T> 1692 inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter() 1693 { 1694 const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>(); 1695 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) { 1696 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o; 1697 return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o); 1698 } 1699 return true; 1700 } +/ 1701 1702 extern(C++, "QtPrivate") { 1703 1704 /+ template<typename From> 1705 struct QSequentialIterableConvertFunctor 1706 { 1707 QIterable<QMetaSequence> operator()(const From &f) const 1708 { 1709 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f); 1710 } 1711 }; +/ 1712 1713 struct QSequentialIterableMutableViewFunctor(From) 1714 { 1715 /+ValueClass!(QIterable!(QMetaSequence)) operator ()(ref From f) const 1716 { 1717 return QIterable!(QMetaSequence)(QMetaSequence.fromContainer!(From)(), &f); 1718 }+/ 1719 } 1720 1721 /+ template<typename T> 1722 struct SequentialValueTypeIsMetaType<T, true> 1723 { 1724 static bool registerConverter() 1725 { 1726 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>(); 1727 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) { 1728 QSequentialIterableConvertFunctor<T> o; 1729 return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o); 1730 } 1731 return true; 1732 } 1733 1734 static bool registerMutableView() 1735 { 1736 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>(); 1737 if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) { 1738 QSequentialIterableMutableViewFunctor<T> o; 1739 return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o); 1740 } 1741 return true; 1742 } 1743 }; 1744 1745 template<typename From> 1746 struct QAssociativeIterableConvertFunctor 1747 { 1748 QIterable<QMetaAssociation> operator()(const From &f) const 1749 { 1750 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f); 1751 } 1752 }; +/ 1753 1754 struct QAssociativeIterableMutableViewFunctor(From) 1755 { 1756 /+ValueClass!(QIterable!(QMetaAssociation)) operator ()(ref From f) const 1757 { 1758 return QIterable!(QMetaAssociation)(QMetaAssociation.fromContainer!(From)(), &f); 1759 }+/ 1760 } 1761 1762 // Mapped type can be omitted, for example in case of a set. 1763 // However, if it is available, we want to instantiate the metatype here. 1764 /+ template<typename T> 1765 struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T> 1766 { 1767 static bool registerConverter() 1768 { 1769 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>(); 1770 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) { 1771 QAssociativeIterableConvertFunctor<T> o; 1772 return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o); 1773 } 1774 return true; 1775 } 1776 1777 static bool registerMutableView() 1778 { 1779 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>(); 1780 if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) { 1781 QAssociativeIterableMutableViewFunctor<T> o; 1782 return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o); 1783 } 1784 return true; 1785 } 1786 }; +/ 1787 1788 struct QTypeNormalizer 1789 { 1790 char* output; 1791 int len = 0; 1792 char last = 0; 1793 1794 private: 1795 static bool is_ident_char(char s) 1796 { 1797 return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9') 1798 || s == '_'); 1799 } 1800 static bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); } 1801 static bool is_number(char s) { return s >= '0' && s <= '9'; } 1802 static bool starts_with_token(const(char)* b, const(char)* e, const(char)* token, 1803 bool msvcKw = false) 1804 { 1805 while (b != e && *token && *b == *token) { 1806 b++; 1807 token++; 1808 } 1809 if (*token) 1810 return false; 1811 /+ #ifdef Q_CC_MSVC 1812 /// On MSVC, keywords like class or struct are not separated with spaces in constexpr 1813 /// context 1814 if (msvcKw) 1815 return true; 1816 #endif 1817 Q_UNUSED(msvcKw) +/ 1818 return b == e || !is_ident_char(*b); 1819 } 1820 static bool skipToken(ref const(char)* x, const(char)* e, const(char)* token, 1821 bool msvcKw = false) 1822 { 1823 if (!starts_with_token(x, e, token, msvcKw)) 1824 return false; 1825 while (*token++) 1826 x++; 1827 while (x != e && is_space(*x)) 1828 x++; 1829 return true; 1830 } 1831 static const(char)* skipString(const(char)* x, const(char)* e) 1832 { 1833 char delim = *x; 1834 x++; 1835 while (x != e && *x != delim) { 1836 if (*x == '\\') { 1837 x++; 1838 if (x == e) 1839 return e; 1840 } 1841 x++; 1842 } 1843 if (x != e) 1844 x++; 1845 return x; 1846 }/+ ; +/ 1847 static const(char)* skipTemplate(const(char)* x, const(char)* e, bool stopAtComa = false) 1848 { 1849 int scopeDepth = 0; 1850 int templateDepth = 0; 1851 while (x != e) { 1852 switch (*x) { 1853 case '<': 1854 if (!scopeDepth) 1855 templateDepth++; 1856 break; 1857 case ',': 1858 if (stopAtComa && !scopeDepth && !templateDepth) 1859 return x; 1860 break; 1861 case '>': 1862 if (!scopeDepth) 1863 if (--templateDepth < 0) 1864 return x; 1865 break; 1866 case '(': 1867 case '[': 1868 case '{': 1869 scopeDepth++; 1870 break; 1871 case '}': 1872 case ']': 1873 case ')': 1874 scopeDepth--; 1875 break; 1876 case '\'': 1877 if (is_number(x[-1])) 1878 break; 1879 goto case; 1880 case '\"': 1881 x = skipString(x, e); 1882 continue;default: 1883 1884 } 1885 x++; 1886 } 1887 return x; 1888 }/+ ; +/ 1889 1890 void append(char x) 1891 { 1892 last = x; 1893 len++; 1894 if (output) 1895 *output++ = x; 1896 } 1897 1898 void replaceLast(char x) 1899 { 1900 last = x; 1901 if (output) 1902 *(output - 1) = x; 1903 } 1904 1905 void appendStr(const(char)* x) 1906 { 1907 while (*x) 1908 append(*x++); 1909 }/+ ; +/ 1910 1911 void normalizeIntegerTypes(ref const(char)* begin, const(char)* end) 1912 { 1913 int numLong = 0; 1914 int numSigned = 0; 1915 int numUnsigned = 0; 1916 int numInt = 0; 1917 int numShort = 0; 1918 int numChar = 0; 1919 while (begin < end) { 1920 if (skipToken(begin, end, "long")) { 1921 numLong++; 1922 continue; 1923 } 1924 if (skipToken(begin, end, "int")) { 1925 numInt++; 1926 continue; 1927 } 1928 if (skipToken(begin, end, "short")) { 1929 numShort++; 1930 continue; 1931 } 1932 if (skipToken(begin, end, "unsigned")) { 1933 numUnsigned++; 1934 continue; 1935 } 1936 if (skipToken(begin, end, "signed")) { 1937 numSigned++; 1938 continue; 1939 } 1940 if (skipToken(begin, end, "char")) { 1941 numChar++; 1942 continue; 1943 } 1944 /+ #ifdef Q_CC_MSVC 1945 if (skipToken(begin, end, "__int64")) { 1946 numLong = 2; 1947 continue; 1948 } 1949 #endif +/ 1950 break; 1951 } 1952 if (numLong == 2) 1953 append('q'); // q(u)longlong 1954 if (numSigned && numChar) 1955 appendStr("signed "); 1956 else if (numUnsigned) 1957 appendStr("u"); 1958 if (numChar) 1959 appendStr("char"); 1960 else if (numShort) 1961 appendStr("short"); 1962 else if (numLong == 1) 1963 appendStr("long"); 1964 else if (numLong == 2) 1965 appendStr("longlong"); 1966 else if (numUnsigned || numSigned || numInt) 1967 appendStr("int"); 1968 } 1969 1970 void skipStructClassOrEnum(ref const(char)* begin, const(char)* end) 1971 { 1972 // discard 'struct', 'class', and 'enum'; they are optional 1973 // and we don't want them in the normalized signature 1974 skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true) 1975 || skipToken(begin, end, "enum", true); 1976 } 1977 1978 void skipQtNamespace(ref const(char)* begin, const(char)* end) 1979 { 1980 /+ #ifdef QT_NAMESPACE 1981 const char *nsbeg = begin; 1982 if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':' 1983 && nsbeg[1] == ':') { 1984 begin = nsbeg + 2; 1985 while (begin != end && is_space(*begin)) 1986 begin++; 1987 } 1988 #else 1989 Q_UNUSED(begin) +/ 1990 /+ Q_UNUSED(end) +/ 1991 /+ #endif +/ 1992 } 1993 1994 public: 1995 /+ #if defined(Q_CC_CLANG) || defined (Q_CC_GNU) +/ 1996 // this is much simpler than the full type normalization below 1997 // the reason is that the signature returned by Q_FUNC_INFO is already 1998 // normalized to the largest degree, and we need to do only small adjustments 1999 /+int normalizeTypeFromSignature(const(char)* begin, const(char)* end) 2000 { 2001 // bail out if there is an anonymous struct 2002 auto name = /+ std:: +/string_view(begin, end-begin); 2003 /+ #if defined (Q_CC_CLANG) 2004 if (name.find("anonymous ") != std::string_view::npos) 2005 return normalizeType(begin, end); 2006 #else +/ 2007 if (name.find("unnamed ".ptr) != /+ std:: +/string_view.npos) 2008 return normalizeType(begin, end); 2009 /+ #endif +/ 2010 while (begin < end) { 2011 if (*begin == ' ') { 2012 if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') { 2013 ++begin; 2014 continue; 2015 } 2016 } 2017 if (last == ' ') { 2018 if (*begin == '*' || *begin == '&' || *begin == '(') { 2019 replaceLast(*begin); 2020 ++begin; 2021 continue; 2022 } 2023 } 2024 if (!is_ident_char(last)) { 2025 skipStructClassOrEnum(begin, end); 2026 if (begin == end) 2027 break; 2028 2029 skipQtNamespace(begin, end); 2030 if (begin == end) 2031 break; 2032 2033 normalizeIntegerTypes(begin, end); 2034 if (begin == end) 2035 break; 2036 } 2037 append(*begin); 2038 ++begin; 2039 } 2040 return len; 2041 }+/ 2042 /+ #else 2043 // MSVC needs the full normalization, as it puts the const in a different 2044 // place than we expect 2045 constexpr int normalizeTypeFromSignature(const char *begin, const char *end) 2046 { return normalizeType(begin, end); } 2047 #endif +/ 2048 2049 int normalizeType(const(char)* begin, const(char)* end, bool adjustConst = true) 2050 { 2051 // Trim spaces 2052 while (begin != end && is_space(*begin)) 2053 begin++; 2054 while (begin != end && is_space(*(end - 1))) 2055 end--; 2056 2057 // Convert 'char const *' into 'const char *'. Start at index 1, 2058 // not 0, because 'const char *' is already OK. 2059 const(char)* cst = begin + 1; 2060 if (*begin == '\'' || *begin == '"') 2061 cst = skipString(begin, end); 2062 bool seenStar = false; 2063 bool hasMiddleConst = false; 2064 while (cst < end) { 2065 if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) { 2066 cst = skipString(cst, end); 2067 if (cst == end) 2068 break; 2069 } 2070 2071 // We mustn't convert 'char * const *' into 'const char **' 2072 // and we must beware of 'Bar<const Bla>'. 2073 if (*cst == '&' || *cst == '*' || *cst == '[') { 2074 seenStar = *cst != '&' || cst != (end - 1); 2075 break; 2076 } 2077 if (*cst == '<') { 2078 cst = skipTemplate(cst + 1, end); 2079 if (cst == end) 2080 break; 2081 } 2082 cst++; 2083 const(char)* skipedCst = cst; 2084 if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) { 2085 const(char)* testEnd = end; 2086 while (skipedCst < testEnd--) { 2087 if (*testEnd == '*' || *testEnd == '[' 2088 || (*testEnd == '&' && testEnd != (end - 1))) { 2089 seenStar = true; 2090 break; 2091 } 2092 if (*testEnd == '>') 2093 break; 2094 } 2095 if (adjustConst && !seenStar) { 2096 if (*(end - 1) == '&') 2097 end--; 2098 } else { 2099 appendStr("const "); 2100 } 2101 normalizeType(begin, cst, false); 2102 begin = skipedCst; 2103 hasMiddleConst = true; 2104 break; 2105 } 2106 } 2107 if (skipToken(begin, end, "const")) { 2108 if (adjustConst && !seenStar) { 2109 if (*(end - 1) == '&') 2110 end--; 2111 } else { 2112 appendStr("const "); 2113 } 2114 } 2115 if (seenStar && adjustConst) { 2116 const(char)* e = end; 2117 if (*(end - 1) == '&' && *(end - 2) != '&') 2118 e--; 2119 while (begin != e && is_space(*(e - 1))) 2120 e--; 2121 const(char)* token = "tsnoc"; // 'const' reverse, to check if it ends with const 2122 while (*token && begin != e && *(--e) == *token++) 2123 {} 2124 if (!*token && begin != e && !is_ident_char(*(e - 1))) { 2125 while (begin != e && is_space(*(e - 1))) 2126 e--; 2127 end = e; 2128 } 2129 } 2130 2131 skipStructClassOrEnum(begin, end); 2132 skipQtNamespace(begin, end); 2133 2134 if (skipToken(begin, end, "QVector")) { 2135 // Replace QVector by QList 2136 appendStr("QList"); 2137 } 2138 2139 if (skipToken(begin, end, "QPair")) { 2140 // replace QPair by std::pair 2141 appendStr("std::pair"); 2142 } 2143 2144 if (!hasMiddleConst) 2145 // Normalize the integer types 2146 normalizeIntegerTypes(begin, end); 2147 2148 bool spaceSkiped = true; 2149 while (begin != end) { 2150 char c = *begin++; 2151 if (is_space(c)) { 2152 spaceSkiped = true; 2153 } else if ((c == '\'' && !is_number(last)) || c == '\"') { 2154 begin--; 2155 auto x = skipString(begin, end); 2156 while (begin < x) 2157 append(*begin++); 2158 } else { 2159 if (spaceSkiped && is_ident_char(last) && is_ident_char(c)) 2160 append(' '); 2161 append(c); 2162 spaceSkiped = false; 2163 if (c == '<') { 2164 do { 2165 // template recursion 2166 const(char)* tpl = skipTemplate(begin, end, true); 2167 normalizeType(begin, tpl, false); 2168 if (tpl == end) 2169 return len; 2170 append(*tpl); 2171 begin = tpl; 2172 } while (*begin++ == ','); 2173 } 2174 } 2175 } 2176 return len; 2177 } 2178 } 2179 2180 // Normalize the type between begin and end, and store the data in the output. Returns the length. 2181 // The idea is to first run this function with nullptr as output to allocate the output with the 2182 // size 2183 /+int qNormalizeType(const(char)* begin, const(char)* end, char* output) 2184 { 2185 return QTypeNormalizer { output} .normalizeType(begin, end); 2186 }+/ 2187 2188 /+ template<typename T> 2189 struct is_std_pair : std::false_type {}; 2190 2191 template <typename T1_, typename T2_> 2192 struct is_std_pair<std::pair<T1_, T2_>> : std::true_type { 2193 using T1 = T1_; 2194 using T2 = T2_; 2195 }; +/ 2196 2197 extern(D) auto typenameHelper(T)() 2198 { 2199 /+ if constexpr (is_std_pair<T>::value) { 2200 using T1 = typename is_std_pair<T>::T1; 2201 using T2 = typename is_std_pair<T>::T2; 2202 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {}; 2203 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {}; 2204 if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) { 2205 t1Name = QMetaTypeId2<T1>::nameAsArray; 2206 } else { 2207 t1Name = typenameHelper<T1>(); 2208 } 2209 if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) { 2210 t2Name = QMetaTypeId2<T2>::nameAsArray; 2211 } else { 2212 t2Name = typenameHelper<T2>(); 2213 } 2214 constexpr auto nonTypeDependentLen = sizeof("std::pair<,>"); 2215 constexpr auto t1Len = t1Name.size() - 1; 2216 constexpr auto t2Len = t2Name.size() - 1; 2217 constexpr auto length = nonTypeDependentLen + t1Len + t2Len; 2218 std::array<char, length + 1> result {}; 2219 constexpr auto prefix = "std::pair<"; 2220 int currentLength = 0; 2221 for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength) 2222 result[currentLength] = prefix[currentLength]; 2223 for (int i = 0; i < int(t1Len); ++currentLength, ++i) 2224 result[currentLength] = t1Name[i]; 2225 result[currentLength++] = ','; 2226 for (int i = 0; i < int(t2Len); ++currentLength, ++i) 2227 result[currentLength] = t2Name[i]; 2228 result[currentLength++] = '>'; 2229 result[currentLength++] = '\0'; 2230 return result; 2231 } else +/ { 2232 immutable(char[T.stringof.length + 1]) result = T.stringof; 2233 //QTypeNormalizer{ result.data()} .normalizeTypeFromSignature(begin, end); 2234 // TODO: Use the same name as Qt. 2235 return result; 2236 } 2237 } 2238 2239 struct BuiltinMetaType(T) 2240 { 2241 static if(QMetaTypeId2!(T).IsBuiltIn) 2242 enum int value = QMetaTypeId2!(T).MetaType; 2243 else 2244 enum int value = 0; 2245 } 2246 2247 struct QEqualityOperatorForType(T, /+ bool +/ /+ = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>) +/) 2248 { 2249 /+ QT_WARNING_PUSH 2250 QT_WARNING_DISABLE_FLOAT_COMPARE +/ 2251 static bool equals(const(QMetaTypeInterface)* , const(void)* a, const(void)* b) 2252 { return *reinterpret_cast!(const(T)*)(a) == *reinterpret_cast!(const(T)*)(b); } 2253 /+ QT_WARNING_POP +/ 2254 } 2255 2256 /+ template<typename T> 2257 struct QEqualityOperatorForType <T, false> 2258 { 2259 static constexpr QMetaTypeInterface::EqualsFn equals = nullptr; 2260 }; +/ 2261 2262 struct QLessThanOperatorForType(T, /+ bool +/ /+ = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>) +/) 2263 { 2264 static bool lessThan(const(QMetaTypeInterface)* , const(void)* a, const(void)* b) 2265 { return *reinterpret_cast!(const(T)*)(a) < *reinterpret_cast!(const(T)*)(b); } 2266 } 2267 2268 /+ template<typename T> 2269 struct QLessThanOperatorForType <T, false> 2270 { 2271 static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr; 2272 }; +/ 2273 2274 struct QDebugStreamOperatorForType(T, /+ bool +/ /+ = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>) +/) 2275 { 2276 /+ static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a) 2277 { dbg << *reinterpret_cast<const T *>(a); } +/ 2278 } 2279 2280 /+ template<typename T> 2281 struct QDebugStreamOperatorForType <T, false> 2282 { 2283 static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr; 2284 }; +/ 2285 2286 2287 struct QDataStreamOperatorForType(T, /+ bool +/ /+ = QTypeTraits::has_stream_operator_v<QDataStream, T>> +/) 2288 { 2289 static void dataStreamOut(const(QMetaTypeInterface)* , ref QDataStream ds, const(void)* a) 2290 { ds << *reinterpret_cast!(const(T)*)(a); } 2291 static void dataStreamIn(const(QMetaTypeInterface)* , ref QDataStream ds, void* a) 2292 { ds >> *reinterpret_cast!(T*)(a); } 2293 } 2294 2295 /+ template<typename T> 2296 struct QDataStreamOperatorForType <T, false> 2297 { 2298 static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr; 2299 static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr; 2300 }; +/ 2301 2302 class QMetaTypeForType(S) 2303 { 2304 public: 2305 extern(D) static immutable name = typenameHelper!(S)(); 2306 2307 static QMetaTypeInterface.DefaultCtrFn getDefaultCtr() 2308 { 2309 import core.lifetime; 2310 2311 static if (__traits(compiles, {S s;}) || __traits(hasMember, S, "rawConstructor")) { 2312 return (const QMetaTypeInterface *, void *addr) { 2313 static if(__traits(hasMember, S, "rawConstructor")) { 2314 (cast(S*)addr).rawConstructor(); 2315 } else { 2316 emplace!S(cast(S*)addr); 2317 } 2318 }; 2319 } else { 2320 return null; 2321 } 2322 } 2323 2324 static QMetaTypeInterface.CopyCtrFn getCopyCtr() 2325 { 2326 import core.lifetime; 2327 2328 static if (__traits(compiles, (ref S other){S s = other;})) { 2329 return (const QMetaTypeInterface *, void *addr, const void *other) { 2330 static if(is(S == struct) && __traits(hasCopyConstructor, S)) { 2331 // Workaround for https://issues.dlang.org/show_bug.cgi?id=22766 2332 import core.stdc.string; 2333 memset(addr, 0, S.sizeof); 2334 (*cast(S*)addr).__ctor(*cast(S*)other); 2335 } else { 2336 copyEmplace!S(*cast(S*)other, *cast(S*)addr); 2337 } 2338 }; 2339 } else { 2340 return null; 2341 } 2342 } 2343 2344 static QMetaTypeInterface.MoveCtrFn getMoveCtr() 2345 { 2346 import core.lifetime; 2347 2348 static if (0 /*/+ std:: +/is_move_constructible_v!(S)*/) { 2349 return (const QMetaTypeInterface *, void *addr, void *other) { 2350 emplace!S(cast(S*)addr, /+ std:: +/move(*reinterpret_cast!(S*)(other))); 2351 }; 2352 } else { 2353 return null; 2354 } 2355 } 2356 2357 static QMetaTypeInterface.DtorFn getDtor() 2358 { 2359 static if (1 /*/+ std:: +/is_destructible_v!(S) && !/+ std:: +/is_trivially_destructible_v!(S)*/) 2360 return (const QMetaTypeInterface *, void *addr) { 2361 destroy!false(*reinterpret_cast!(S*)(addr)); 2362 }; 2363 else 2364 return null; 2365 } 2366 2367 static QMetaTypeInterface.LegacyRegisterOp getLegacyRegister() 2368 { 2369 static if (QMetaTypeId2!(S).Defined && !QMetaTypeId2!(S).IsBuiltIn) { 2370 return () { QMetaTypeId2!(S).qt_metatype_id(); }; 2371 } else { 2372 return null; 2373 } 2374 } 2375 2376 static const(char)* getName() 2377 { 2378 static if (cast(bool)(QMetaTypeId2!(S).IsBuiltIn)) { 2379 return QMetaTypeId2!(S).nameAsArray.ptr; 2380 } else { 2381 return name.ptr; 2382 } 2383 } 2384 } 2385 2386 2387 struct QMetaTypeInterfaceWrapper(T) 2388 { 2389 extern(D) static immutable QMetaTypeInterface metaType = { 2390 /*.revision=*/ 0, 2391 /*.alignment=*/ T.alignof, 2392 /*.size=*/ T.sizeof, 2393 /*.flags=*/ QMetaTypeTypeFlags!(T).Flags, 2394 /*.typeId=*/ QBasicAtomicInt(BuiltinMetaType!(T).value), 2395 /*.metaObjectFn=*/ MetaObjectForType!(T).metaObjectFunction, 2396 /*.name=*/ QMetaTypeForType!(T).getName(), 2397 /*.defaultCtr=*/ QMetaTypeForType!(T).getDefaultCtr(), 2398 /*.copyCtr=*/ QMetaTypeForType!(T).getCopyCtr(), 2399 /*.moveCtr=*/ QMetaTypeForType!(T).getMoveCtr(), 2400 /*.dtor=*/ QMetaTypeForType!(T).getDtor(), 2401 // /*.equals=*/ &QEqualityOperatorForType!(T).equals, 2402 // /*.lessThan=*/ &QLessThanOperatorForType!(T).lessThan, 2403 // /*.debugStream=*/ QDebugStreamOperatorForType!(T).debugStream, 2404 // /*.dataStreamOut=*/ &QDataStreamOperatorForType!(T).dataStreamOut, 2405 // /*.dataStreamIn=*/ &QDataStreamOperatorForType!(T).dataStreamIn, 2406 // /*.legacyRegisterOp=*/ QMetaTypeForType!(T).getLegacyRegister() 2407 }; 2408 }; 2409 2410 2411 struct QMetaTypeInterfaceWrapper(T: void) 2412 { 2413 static immutable QMetaTypeInterface metaType = 2414 { 2415 /*.revision=*/ 0, 2416 /*.alignment=*/ 0, 2417 /*.size=*/ 0, 2418 /*.flags=*/ 0, 2419 /*.typeId=*/ BuiltinMetaType!(void).value, 2420 /*.metaObjectFn=*/ null, 2421 /*.name=*/ "void", 2422 /*.defaultCtr=*/ null, 2423 /*.copyCtr=*/ null, 2424 /*.moveCtr=*/ null, 2425 /*.dtor=*/ null, 2426 /*.equals=*/ null, 2427 /*.lessThan=*/ null, 2428 /*.debugStream=*/ null, 2429 /*.dataStreamOut=*/ null, 2430 /*.dataStreamIn=*/ null, 2431 /*.legacyRegisterOp=*/ null 2432 }; 2433 }; 2434 /+ #undef QT_METATYPE_CONSTEXPRLAMDA 2435 2436 #ifndef QT_BOOTSTRAPPED 2437 2438 #if !defined(Q_CC_MSVC) || !defined(QT_BUILD_CORE_LIB) 2439 #define QT_METATYPE_TEMPLATE_EXPORT Q_CORE_EXPORT 2440 #else 2441 #define QT_METATYPE_TEMPLATE_EXPORT 2442 #endif 2443 2444 #define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \ 2445 extern template class QT_METATYPE_TEMPLATE_EXPORT QMetaTypeForType<Name>; 2446 QT_WARNING_PUSH 2447 QT_WARNING_DISABLE_GCC("-Wattributes") // false positive because of QMetaTypeForType<void> 2448 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) 2449 QT_WARNING_POP 2450 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) 2451 QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) 2452 QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) 2453 QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) 2454 #undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER 2455 #undef QT_METATYPE_TEMPLATE_EXPORT 2456 #endif +/ 2457 2458 const(QMetaTypeInterface)* qMetaTypeInterfaceForType(T)() 2459 { 2460 import std.traits; 2461 alias Ty = Unqual!(T); 2462 return &QMetaTypeInterfaceWrapper!(Ty).metaType; 2463 } 2464 2465 extern(C++, "detail") { 2466 /+struct is_complete_helper(T, ODR_VIOLATION_PREVENTER) 2467 { 2468 /+ template<typename U> +/ 2469 static auto check(U)()/+ (U *) -> std::integral_constant<bool, sizeof(U) != 0> +/; 2470 static auto check()/+ (...) -> std::false_type +/; 2471 alias type = /+ decltype(check(static_cast<T *>(nullptr))) +/false_type; 2472 }+/ 2473 } // namespace detail 2474 2475 struct is_complete(T, ODR_VIOLATION_PREVENTER) { 2476 /+ detail:: +/is_complete_helper!(T, ODR_VIOLATION_PREVENTER).is_complete_helper.type base0; 2477 alias base0 this; 2478 } 2479 2480 struct qRemovePointerLike(T) 2481 { 2482 alias type = /+ std:: +/remove_pointer_t!(T); 2483 } 2484 2485 /+ #define Q_REMOVE_POINTER_LIKE_IMPL(Pointer) \ 2486 template <typename T> \ 2487 struct qRemovePointerLike<Pointer<T>> \ 2488 { \ 2489 using type = T; \ 2490 }; 2491 2492 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_REMOVE_POINTER_LIKE_IMPL) +/ 2493 alias qRemovePointerLike_t(T) = qRemovePointerLike!(T).type; 2494 /+ #undef Q_REMOVE_POINTER_LIKE_IMPL +/ 2495 2496 struct TypeAndForceComplete(T, ForceComplete_) 2497 { 2498 alias type = T; 2499 alias ForceComplete = ForceComplete_; 2500 } 2501 2502 /+ template<typename Unique, typename TypeCompletePair> 2503 constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType() 2504 { 2505 using T = typename TypeCompletePair::type; 2506 using ForceComplete = typename TypeCompletePair::ForceComplete; 2507 using Ty = std::remove_cv_t<std::remove_reference_t<T>>; 2508 using Tz = qRemovePointerLike_t<Ty>; 2509 if constexpr (!is_complete<Tz, Unique>::value && !ForceComplete::value) { 2510 return nullptr; 2511 } else { 2512 return &QMetaTypeInterfaceWrapper<Ty>::metaType; 2513 } 2514 } +/ 2515 2516 } // namespace QtPrivate 2517 2518 /+ template<typename T> 2519 constexpr QMetaType QMetaType::fromType() 2520 { 2521 return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>()); 2522 } 2523 2524 template<typename... T> 2525 constexpr const QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = { 2526 QtPrivate::qMetaTypeInterfaceForType<T>()... 2527 }; 2528 2529 template<typename Unique,typename... T> 2530 constexpr const QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = { 2531 QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()... 2532 }; +/ 2533 2534 template qt_incomplete_metaTypeArray(Unique, T...) 2535 { 2536 mixin((){ 2537 import std.conv; 2538 string code = text("extern(D) const __gshared QMetaTypeInterface*[", T.length, "] qt_incomplete_metaTypeArray = ["); 2539 code ~= "T"; 2540 code ~= "];"; 2541 return code; 2542 }()); 2543 } 2544 2545 /+ Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl) +/ 2546