1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QMETACONTAINER_H
5#define QMETACONTAINER_H
6
7#include <QtCore/qcontainerinfo.h>
8#include <QtCore/qflags.h>
9#include <QtCore/qglobal.h>
10
11#include <iterator>
12
13QT_BEGIN_NAMESPACE
14
15class QMetaType;
16namespace QtPrivate {
17class QMetaTypeInterface;
18template<typename T>
19constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
20}
21
22namespace QtMetaContainerPrivate {
23
24enum IteratorCapability : quint8 {
25 InputCapability = 1 << 0,
26 ForwardCapability = 1 << 1,
27 BiDirectionalCapability = 1 << 2,
28 RandomAccessCapability = 1 << 3,
29};
30
31Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
32Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
33
34enum AddRemoveCapability : quint8 {
35 CanAddAtBegin = 1 << 0,
36 CanRemoveAtBegin = 1 << 1,
37 CanAddAtEnd = 1 << 2,
38 CanRemoveAtEnd = 1 << 3
39};
40Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
41Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
42
43class QMetaContainerInterface
44{
45public:
46 enum Position : quint8 { AtBegin, AtEnd, Unspecified };
47 ushort revision = 0;
48 IteratorCapabilities iteratorCapabilities;
49
50 using SizeFn = qsizetype(*)(const void *);
51 SizeFn sizeFn;
52 using ClearFn = void(*)(void *);
53 ClearFn clearFn;
54
55 using CreateIteratorFn = void *(*)(void *, Position);
56 CreateIteratorFn createIteratorFn;
57 using DestroyIteratorFn = void(*)(const void *);
58 DestroyIteratorFn destroyIteratorFn;
59 using CompareIteratorFn = bool(*)(const void *, const void *);
60 CompareIteratorFn compareIteratorFn;
61 using CopyIteratorFn = void(*)(void *, const void *);
62 CopyIteratorFn copyIteratorFn;
63 using AdvanceIteratorFn = void(*)(void *, qsizetype);
64 AdvanceIteratorFn advanceIteratorFn;
65 using DiffIteratorFn = qsizetype(*)(const void *, const void *);
66 DiffIteratorFn diffIteratorFn;
67
68 using CreateConstIteratorFn = void *(*)(const void *, Position);
69 CreateConstIteratorFn createConstIteratorFn;
70 DestroyIteratorFn destroyConstIteratorFn;
71 CompareIteratorFn compareConstIteratorFn;
72 CopyIteratorFn copyConstIteratorFn;
73 AdvanceIteratorFn advanceConstIteratorFn;
74 DiffIteratorFn diffConstIteratorFn;
75
76 QMetaContainerInterface() = default;
77
78 template<typename MetaContainer>
79 constexpr QMetaContainerInterface(const MetaContainer &)
80 : iteratorCapabilities(MetaContainer::getIteratorCapabilities())
81 , sizeFn(MetaContainer::getSizeFn())
82 , clearFn(MetaContainer::getClearFn())
83 , createIteratorFn(MetaContainer::getCreateIteratorFn())
84 , destroyIteratorFn(MetaContainer::getDestroyIteratorFn())
85 , compareIteratorFn(MetaContainer::getCompareIteratorFn())
86 , copyIteratorFn(MetaContainer::getCopyIteratorFn())
87 , advanceIteratorFn(MetaContainer::getAdvanceIteratorFn())
88 , diffIteratorFn(MetaContainer::getDiffIteratorFn())
89 , createConstIteratorFn(MetaContainer::getCreateConstIteratorFn())
90 , destroyConstIteratorFn(MetaContainer::getDestroyConstIteratorFn())
91 , compareConstIteratorFn(MetaContainer::getCompareConstIteratorFn())
92 , copyConstIteratorFn(MetaContainer::getCopyConstIteratorFn())
93 , advanceConstIteratorFn(MetaContainer::getAdvanceConstIteratorFn())
94 , diffConstIteratorFn(MetaContainer::getDiffConstIteratorFn())
95 {}
96};
97
98class QMetaSequenceInterface : public QMetaContainerInterface
99{
100public:
101 const QtPrivate::QMetaTypeInterface *valueMetaType;
102 AddRemoveCapabilities addRemoveCapabilities;
103
104 using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
105 ValueAtIndexFn valueAtIndexFn;
106 using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
107 SetValueAtIndexFn setValueAtIndexFn;
108
109 using AddValueFn = void(*)(void *, const void *, Position);
110 AddValueFn addValueFn;
111 using RemoveValueFn = void(*)(void *, Position);
112 RemoveValueFn removeValueFn;
113
114 using ValueAtIteratorFn = void(*)(const void *, void *);
115 ValueAtIteratorFn valueAtIteratorFn;
116 using SetValueAtIteratorFn = void(*)(const void *, const void *);
117 SetValueAtIteratorFn setValueAtIteratorFn;
118 using InsertValueAtIteratorFn = void(*)(void *, const void *, const void *);
119 InsertValueAtIteratorFn insertValueAtIteratorFn;
120
121 ValueAtIteratorFn valueAtConstIteratorFn;
122
123 using EraseValueAtIteratorFn = void(*)(void *, const void *);
124 EraseValueAtIteratorFn eraseValueAtIteratorFn;
125
126 using EraseRangeAtIteratorFn = void(*)(void *, const void *, const void *);
127 EraseRangeAtIteratorFn eraseRangeAtIteratorFn;
128
129 QMetaSequenceInterface() = default;
130
131 template<typename MetaSequence>
132 constexpr QMetaSequenceInterface(const MetaSequence &m)
133 : QMetaContainerInterface(m)
134 , valueMetaType(MetaSequence::getValueMetaType())
135 , addRemoveCapabilities(MetaSequence::getAddRemoveCapabilities())
136 , valueAtIndexFn(MetaSequence::getValueAtIndexFn())
137 , setValueAtIndexFn(MetaSequence::getSetValueAtIndexFn())
138 , addValueFn(MetaSequence::getAddValueFn())
139 , removeValueFn(MetaSequence::getRemoveValueFn())
140 , valueAtIteratorFn(MetaSequence::getValueAtIteratorFn())
141 , setValueAtIteratorFn(MetaSequence::getSetValueAtIteratorFn())
142 , insertValueAtIteratorFn(MetaSequence::getInsertValueAtIteratorFn())
143 , valueAtConstIteratorFn(MetaSequence::getValueAtConstIteratorFn())
144 , eraseValueAtIteratorFn(MetaSequence::getEraseValueAtIteratorFn())
145 , eraseRangeAtIteratorFn(MetaSequence::getEraseRangeAtIteratorFn())
146 {}
147};
148
149class QMetaAssociationInterface : public QMetaContainerInterface
150{
151public:
152 const QtPrivate::QMetaTypeInterface *keyMetaType;
153 const QtPrivate::QMetaTypeInterface *mappedMetaType;
154
155 using InsertKeyFn = void(*)(void *, const void *);
156 InsertKeyFn insertKeyFn;
157 using RemoveKeyFn = void(*)(void *, const void *);
158 RemoveKeyFn removeKeyFn;
159 using ContainsKeyFn = bool(*)(const void *, const void *);
160 ContainsKeyFn containsKeyFn;
161
162 using MappedAtKeyFn = void(*)(const void *, const void *, void *);
163 MappedAtKeyFn mappedAtKeyFn;
164 using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
165 SetMappedAtKeyFn setMappedAtKeyFn;
166
167 using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
168 CreateIteratorAtKeyFn createIteratorAtKeyFn;
169 using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
170 CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
171
172 using KeyAtIteratorFn = void(*)(const void *, void *);
173 KeyAtIteratorFn keyAtIteratorFn;
174 KeyAtIteratorFn keyAtConstIteratorFn;
175
176 using MappedAtIteratorFn = void(*)(const void *, void *);
177 MappedAtIteratorFn mappedAtIteratorFn;
178 MappedAtIteratorFn mappedAtConstIteratorFn;
179
180 using SetMappedAtIteratorFn = void(*)(const void *, const void *);
181 SetMappedAtIteratorFn setMappedAtIteratorFn;
182
183 using EraseKeyAtIteratorFn = void(*)(void *, const void *);
184 EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
185
186 QMetaAssociationInterface() = default;
187
188 template<typename MetaAssociation>
189 constexpr QMetaAssociationInterface(const MetaAssociation &m)
190 : QMetaContainerInterface(m)
191 , keyMetaType(MetaAssociation::getKeyMetaType())
192 , mappedMetaType(MetaAssociation::getMappedMetaType())
193 , insertKeyFn(MetaAssociation::getInsertKeyFn())
194 , removeKeyFn(MetaAssociation::getRemoveKeyFn())
195 , containsKeyFn(MetaAssociation::getContainsKeyFn())
196 , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
197 , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
198 , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
199 , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
200 , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
201 , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
202 , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
203 , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
204 , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
205 , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
206 {}
207};
208
209template<typename C>
210class QMetaContainerForContainer
211{
212 friend QMetaContainerInterface;
213
214 template <typename Iterator>
215 static constexpr IteratorCapabilities capabilitiesForIterator()
216 {
217 using Tag = typename std::iterator_traits<Iterator>::iterator_category;
218 IteratorCapabilities caps {};
219 if constexpr (std::is_base_of_v<std::input_iterator_tag, Tag>)
220 caps |= InputCapability;
221 if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
222 caps |= ForwardCapability;
223 if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
224 caps |= BiDirectionalCapability;
225 if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
226 caps |= RandomAccessCapability;
227 return caps;
228 }
229
230 static constexpr IteratorCapabilities getIteratorCapabilities()
231 {
232 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>)
233 return capabilitiesForIterator<QContainerInfo::iterator<C>>();
234 else if constexpr (QContainerInfo::has_const_iterator_v<C>)
235 return capabilitiesForIterator<QContainerInfo::const_iterator<C>>();
236 else
237 return {};
238 }
239
240 static constexpr QMetaContainerInterface::SizeFn getSizeFn()
241 {
242 if constexpr (QContainerInfo::has_size_v<C>) {
243 return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
244 } else {
245 return nullptr;
246 }
247 }
248
249 static constexpr QMetaContainerInterface::ClearFn getClearFn()
250 {
251 if constexpr (QContainerInfo::has_clear_v<C>) {
252 return [](void *c) { return static_cast<C *>(c)->clear(); };
253 } else {
254 return nullptr;
255 }
256 }
257
258 static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
259 {
260 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
261 return [](void *c, QMetaContainerInterface::Position p) -> void* {
262 using Iterator = QContainerInfo::iterator<C>;
263 switch (p) {
264 case QMetaContainerInterface::Unspecified:
265 return new Iterator;
266 case QMetaContainerInterface::AtBegin:
267 return new Iterator(static_cast<C *>(c)->begin());
268 case QMetaContainerInterface::AtEnd:
269 return new Iterator(static_cast<C *>(c)->end());
270 }
271 return nullptr;
272 };
273 } else {
274 return nullptr;
275 }
276 }
277
278 static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
279 {
280 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
281 return [](const void *i) {
282 using Iterator = QContainerInfo::iterator<C>;
283 delete static_cast<const Iterator *>(i);
284 };
285 } else {
286 return nullptr;
287 }
288 }
289
290 static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
291 {
292 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
293 return [](const void *i, const void *j) {
294 using Iterator = QContainerInfo::iterator<C>;
295 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
296 };
297 } else {
298 return nullptr;
299 }
300 }
301
302 static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
303 {
304 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
305 return [](void *i, const void *j) {
306 using Iterator = QContainerInfo::iterator<C>;
307 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
308 };
309 } else {
310 return nullptr;
311 }
312 }
313
314 static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
315 {
316 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
317 return [](void *i, qsizetype step) {
318 std::advance(*static_cast<QContainerInfo::iterator<C> *>(i), step);
319 };
320 } else {
321 return nullptr;
322 }
323 }
324
325 static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
326 {
327 if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
328 return [](const void *i, const void *j) -> qsizetype {
329 return std::distance(*static_cast<const QContainerInfo::iterator<C> *>(j),
330 *static_cast<const QContainerInfo::iterator<C> *>(i));
331 };
332 } else {
333 return nullptr;
334 }
335 }
336
337 static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
338 {
339 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
340 return [](const void *c, QMetaContainerInterface::Position p) -> void* {
341 using Iterator = QContainerInfo::const_iterator<C>;
342 switch (p) {
343 case QMetaContainerInterface::Unspecified:
344 return new Iterator;
345 case QMetaContainerInterface::AtBegin:
346 return new Iterator(static_cast<const C *>(c)->begin());
347 case QMetaContainerInterface::AtEnd:
348 return new Iterator(static_cast<const C *>(c)->end());
349 }
350 return nullptr;
351 };
352 } else {
353 return nullptr;
354 }
355 }
356
357 static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
358 {
359 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
360 return [](const void *i) {
361 using Iterator = QContainerInfo::const_iterator<C>;
362 delete static_cast<const Iterator *>(i);
363 };
364 } else {
365 return nullptr;
366 }
367 }
368
369 static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
370 {
371 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
372 return [](const void *i, const void *j) {
373 using Iterator = QContainerInfo::const_iterator<C>;
374 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
375 };
376 } else {
377 return nullptr;
378 }
379 }
380
381 static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
382 {
383 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
384 return [](void *i, const void *j) {
385 using Iterator = QContainerInfo::const_iterator<C>;
386 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
387 };
388 } else {
389 return nullptr;
390 }
391 }
392
393 static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
394 {
395 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
396 return [](void *i, qsizetype step) {
397 std::advance(*static_cast<QContainerInfo::const_iterator<C> *>(i), step);
398 };
399 } else {
400 return nullptr;
401 }
402 }
403
404 static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
405 {
406 if constexpr (QContainerInfo::has_const_iterator_v<C>) {
407 return [](const void *i, const void *j) -> qsizetype {
408 return std::distance(*static_cast<const QContainerInfo::const_iterator<C> *>(j),
409 *static_cast<const QContainerInfo::const_iterator<C> *>(i));
410 };
411 } else {
412 return nullptr;
413 }
414 }
415
416protected:
417
418 template<typename EraseFn>
419 static constexpr EraseFn getEraseAtIteratorFn()
420 {
421 if constexpr (QContainerInfo::has_iterator_v<C>
422 && QContainerInfo::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
423 return [](void *c, const void *i) {
424 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i));
425 };
426 } else {
427 return nullptr;
428 }
429 }
430};
431
432template<typename C>
433class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
434{
435 friend QMetaSequenceInterface;
436
437 static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
438 {
439 if constexpr (QContainerInfo::has_value_type_v<C>)
440 return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
441 else
442 return nullptr;
443 }
444
445 static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
446 {
447 AddRemoveCapabilities caps;
448 if constexpr (QContainerInfo::has_push_back_v<C>)
449 caps |= CanAddAtEnd;
450 if constexpr (QContainerInfo::has_pop_back_v<C>)
451 caps |= CanRemoveAtEnd;
452 if constexpr (QContainerInfo::has_push_front_v<C>)
453 caps |= CanAddAtBegin;
454 if constexpr (QContainerInfo::has_pop_front_v<C>)
455 caps |= CanRemoveAtBegin;
456 return caps;
457 }
458
459 static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
460 {
461 if constexpr (QContainerInfo::has_at_index_v<C>) {
462 return [](const void *c, qsizetype i, void *r) {
463 *static_cast<QContainerInfo::value_type<C> *>(r)
464 = static_cast<const C *>(c)->at(i);
465 };
466 } else if constexpr (QContainerInfo::can_get_at_index_v<C>) {
467 return [](const void *c, qsizetype i, void *r) {
468 *static_cast<QContainerInfo::value_type<C> *>(r)
469 = (*static_cast<const C *>(c))[i];
470 };
471 } else {
472 return nullptr;
473 }
474 }
475
476 static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn()
477 {
478 if constexpr (QContainerInfo::can_set_at_index_v<C>) {
479 return [](void *c, qsizetype i, const void *e) {
480 (*static_cast<C *>(c))[i]
481 = *static_cast<const QContainerInfo::value_type<C> *>(e);
482 };
483 } else {
484 return nullptr;
485 }
486 }
487
488 static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
489 {
490 if constexpr (QContainerInfo::has_push_back_v<C>) {
491 if constexpr (QContainerInfo::has_push_front_v<C>) {
492 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
493 const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
494 switch (position) {
495 case QMetaSequenceInterface::AtBegin:
496 static_cast<C *>(c)->push_front(value);
497 break;
498 case QMetaSequenceInterface::AtEnd:
499 case QMetaSequenceInterface::Unspecified:
500 static_cast<C *>(c)->push_back(value);
501 break;
502 }
503 };
504 } else {
505 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
506 const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
507 switch (position) {
508 case QMetaSequenceInterface::AtBegin:
509 break;
510 case QMetaSequenceInterface::AtEnd:
511 case QMetaSequenceInterface::Unspecified:
512 static_cast<C *>(c)->push_back(value);
513 break;
514 }
515 };
516 }
517 } else if constexpr (QContainerInfo::has_push_front_v<C>) {
518 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
519 const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
520 switch (position) {
521 case QMetaSequenceInterface::Unspecified:
522 case QMetaSequenceInterface::AtBegin:
523 static_cast<C *>(c)->push_front(value);
524 case QMetaSequenceInterface::AtEnd:
525 break;
526 }
527 };
528 } else if constexpr (QContainerInfo::has_insert_v<C>) {
529 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
530 if (position == QMetaSequenceInterface::Unspecified) {
531 static_cast<C *>(c)->insert(
532 *static_cast<const QContainerInfo::value_type<C> *>(v));
533 }
534 };
535 } else {
536 return nullptr;
537 }
538 }
539
540 static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
541 {
542 if constexpr (QContainerInfo::has_pop_back_v<C>) {
543 if constexpr (QContainerInfo::has_pop_front_v<C>) {
544 return [](void *c, QMetaSequenceInterface::Position position) {
545 switch (position) {
546 case QMetaSequenceInterface::AtBegin:
547 static_cast<C *>(c)->pop_front();
548 break;
549 case QMetaSequenceInterface::AtEnd:
550 case QMetaSequenceInterface::Unspecified:
551 static_cast<C *>(c)->pop_back();
552 break;
553 }
554 };
555 } else {
556 return [](void *c, QMetaSequenceInterface::Position position) {
557 switch (position) {
558 case QMetaSequenceInterface::AtBegin:
559 break;
560 case QMetaSequenceInterface::Unspecified:
561 case QMetaSequenceInterface::AtEnd:
562 static_cast<C *>(c)->pop_back();
563 break;
564 }
565 };
566 }
567 } else if constexpr (QContainerInfo::has_pop_front_v<C>) {
568 return [](void *c, QMetaSequenceInterface::Position position) {
569 switch (position) {
570 case QMetaSequenceInterface::Unspecified:
571 case QMetaSequenceInterface::AtBegin:
572 static_cast<C *>(c)->pop_front();
573 break;
574 case QMetaSequenceInterface::AtEnd:
575 break;
576 }
577 };
578 } else {
579 return nullptr;
580 }
581 }
582
583 static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
584 {
585 if constexpr (QContainerInfo::has_iterator_v<C>
586 && QContainerInfo::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
587 return [](const void *i, void *r) {
588 *static_cast<QContainerInfo::value_type<C> *>(r) =
589 *(*static_cast<const QContainerInfo::iterator<C> *>(i));
590 };
591 } else {
592 return nullptr;
593 }
594 }
595
596 static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
597 {
598 if constexpr (QContainerInfo::has_iterator_v<C>
599 && QContainerInfo::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
600 return [](const void *i, const void *e) {
601 *(*static_cast<const QContainerInfo::iterator<C> *>(i))
602 = *static_cast<const QContainerInfo::value_type<C> *>(e);
603 };
604 } else {
605 return nullptr;
606 }
607 }
608
609 static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
610 {
611 if constexpr (QContainerInfo::has_iterator_v<C>
612 && QContainerInfo::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
613 return [](void *c, const void *i, const void *e) {
614 static_cast<C *>(c)->insert(
615 *static_cast<const QContainerInfo::iterator<C> *>(i),
616 *static_cast<const QContainerInfo::value_type<C> *>(e));
617 };
618 } else {
619 return nullptr;
620 }
621 }
622
623 static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
624 {
625 if constexpr (QContainerInfo::has_const_iterator_v<C>
626 && QContainerInfo::iterator_dereferences_to_value_v<C>) {
627 return [](const void *i, void *r) {
628 *static_cast<QContainerInfo::value_type<C> *>(r) =
629 *(*static_cast<const QContainerInfo::const_iterator<C> *>(i));
630 };
631 } else {
632 return nullptr;
633 }
634 }
635
636 static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
637 {
638 return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
639 QMetaSequenceInterface::EraseValueAtIteratorFn>();
640 }
641
642 static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
643 {
644 if constexpr (QContainerInfo::has_iterator_v<C>
645 && QContainerInfo::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
646 return [](void *c, const void *i, const void *j) {
647 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i),
648 *static_cast<const QContainerInfo::iterator<C> *>(j));
649 };
650 } else {
651 return nullptr;
652 }
653 }
654};
655
656template<typename C>
657class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
658{
659 friend QMetaAssociationInterface;
660
661 static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
662 {
663 if constexpr (QContainerInfo::has_key_type_v<C>)
664 return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
665 else
666 return nullptr;
667 }
668
669 static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
670 {
671 if constexpr (QContainerInfo::has_mapped_type_v<C>)
672 return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
673 else
674 return nullptr;
675 }
676
677 static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
678 {
679 if constexpr (QContainerInfo::can_insert_key_v<C>) {
680 return [](void *c, const void *k) {
681 static_cast<C *>(c)->insert(
682 *static_cast<const QContainerInfo::key_type<C> *>(k));
683 };
684 } else if constexpr (QContainerInfo::can_insert_pair_v<C>) {
685 return [](void *c, const void *k) {
686 static_cast<C *>(c)->insert(
687 {*static_cast<const QContainerInfo::key_type<C> *>(k), {}});
688 };
689 } else if constexpr (QContainerInfo::can_insert_key_mapped_v<C>) {
690 return [](void *c, const void *k) {
691 static_cast<C *>(c)->insert(
692 *static_cast<const QContainerInfo::key_type<C> *>(k), {});
693 };
694 } else {
695 return nullptr;
696 }
697 }
698
699 static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
700 {
701 if constexpr (QContainerInfo::can_erase_at_key_v<C>) {
702 return [](void *c, const void *k) {
703 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::key_type<C> *>(k));
704 };
705 } else if constexpr (QContainerInfo::can_remove_at_key_v<C>) {
706 return [](void *c, const void *k) {
707 static_cast<C *>(c)->remove(*static_cast<const QContainerInfo::key_type<C> *>(k));
708 };
709 } else {
710 return nullptr;
711 }
712 }
713
714 static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
715 {
716 if constexpr (QContainerInfo::has_contains_v<C>) {
717 return [](const void *c, const void *k) {
718 return static_cast<const C *>(c)->contains(
719 *static_cast<const QContainerInfo::key_type<C> *>(k));
720 };
721 } else if (QContainerInfo::has_find_v<C>) {
722 return [](const void *c, const void *k) {
723 const C *container = static_cast<const C *>(c);
724 return container->find(
725 *static_cast<const QContainerInfo::key_type<C> *>(k))
726 != container->end();
727 };
728 } else {
729 return nullptr;
730 }
731 }
732
733 static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
734 {
735 if constexpr (QContainerInfo::has_at_key_v<C>) {
736 return [](const void *c, const void *k, void *r) {
737 *static_cast<QContainerInfo::mapped_type<C> *>(r)
738 = static_cast<const C *>(c)->at(
739 *static_cast<const QContainerInfo::key_type<C> *>(k));
740 };
741 } else if constexpr (QContainerInfo::can_get_at_key_v<C>) {
742 return [](const void *c, const void *k, void *r) {
743 *static_cast<QContainerInfo::mapped_type<C> *>(r)
744 = (*static_cast<const C *>(c))[
745 *static_cast<const QContainerInfo::key_type<C> *>(k)];
746 };
747 } else {
748 return nullptr;
749 }
750 }
751
752 static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
753 {
754 if constexpr (QContainerInfo::can_set_at_key_v<C>) {
755 return [](void *c, const void *k, const void *m) {
756 (*static_cast<C *>(c))[*static_cast<const QContainerInfo::key_type<C> *>(k)] =
757 *static_cast<const QContainerInfo::mapped_type<C> *>(m);
758 };
759 } else {
760 return nullptr;
761 }
762 }
763
764 static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
765 {
766 if constexpr (QContainerInfo::has_find_v<C>) {
767 return [](void *c, const void *k) -> void* {
768 using Iterator = QContainerInfo::iterator<C>;
769 return new Iterator(static_cast<C *>(c)->find(
770 *static_cast<const QContainerInfo::key_type<C> *>(k)));
771 };
772 } else {
773 return nullptr;
774 }
775 }
776
777 static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
778 {
779 if constexpr (QContainerInfo::has_find_v<C>) {
780 return [](const void *c, const void *k) -> void* {
781 using Iterator = QContainerInfo::const_iterator<C>;
782 return new Iterator(static_cast<const C *>(c)->find(
783 *static_cast<const QContainerInfo::key_type<C> *>(k)));
784 };
785 } else {
786 return nullptr;
787 }
788 }
789
790 template<typename Iterator>
791 static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
792 {
793 if constexpr (QContainerInfo::iterator_has_key_v<C>) {
794 return [](const void *i, void *k) {
795 *static_cast<QContainerInfo::key_type<C> *>(k)
796 = static_cast<const Iterator *>(i)->key();
797 };
798 } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
799 && QContainerInfo::value_type_has_first_v<C>) {
800 return [](const void *i, void *k) {
801 *static_cast<QContainerInfo::key_type<C> *>(k)
802 = (*static_cast<const Iterator *>(i))->first;
803 };
804 } else if constexpr (QContainerInfo::iterator_dereferences_to_key_v<C>) {
805 return [](const void *i, void *k) {
806 *static_cast<QContainerInfo::key_type<C> *>(k)
807 = *(*static_cast<const Iterator *>(i));
808 };
809 } else {
810 return nullptr;
811 }
812 }
813
814 static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
815 {
816 return keyAtIteratorFn<QContainerInfo::iterator<C>>();
817 }
818
819 static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
820 {
821 return keyAtIteratorFn<QContainerInfo::const_iterator<C>>();
822 }
823
824 template<typename Iterator>
825 static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
826 {
827 if constexpr (QContainerInfo::iterator_has_value_v<C>) {
828 return [](const void *i, void *k) {
829 *static_cast<QContainerInfo::mapped_type<C> *>(k)
830 = static_cast<const Iterator *>(i)->value();
831 };
832 } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
833 && QContainerInfo::value_type_has_second_v<C>) {
834 return [](const void *i, void *k) {
835 *static_cast<QContainerInfo::mapped_type<C> *>(k)
836 = (*static_cast<const Iterator *>(i))->second;
837 };
838 } else if constexpr (QContainerInfo::iterator_dereferences_to_mapped_v<C>) {
839 return [](const void *i, void *k) {
840 *static_cast<QContainerInfo::mapped_type<C> *>(k)
841 = *static_cast<const Iterator *>(i);
842 };
843 } else {
844 return nullptr;
845 }
846 }
847
848 static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
849 {
850 return mappedAtIteratorFn<QContainerInfo::iterator<C>>();
851 }
852
853 static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
854 {
855 return mappedAtIteratorFn<QContainerInfo::const_iterator<C>>();
856 }
857
858 static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
859 {
860 if constexpr (QContainerInfo::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
861 return [](const void *i, const void *m) {
862 *(*static_cast<const QContainerInfo::iterator<C> *>(i))
863 = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
864 };
865 } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
866 && QContainerInfo::value_type_has_second_v<C>) {
867 return [](const void *i, const void *m) {
868 (*static_cast<const QContainerInfo::iterator<C> *>(i))->second
869 = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
870 };
871 } else {
872 return nullptr;
873 }
874 }
875
876 static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
877 {
878 return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
879 QMetaAssociationInterface::EraseKeyAtIteratorFn>();
880 }
881};
882
883} // namespace QtMetaContainerPrivate
884
885class Q_CORE_EXPORT QMetaContainer
886{
887public:
888 QMetaContainer() = default;
889 explicit QMetaContainer(const QtMetaContainerPrivate::QMetaContainerInterface *d) : d_ptr(d) {}
890
891 bool hasInputIterator() const;
892 bool hasForwardIterator() const;
893 bool hasBidirectionalIterator() const;
894 bool hasRandomAccessIterator() const;
895
896 bool hasSize() const;
897 qsizetype size(const void *container) const;
898
899 bool canClear() const;
900 void clear(void *container) const;
901
902 bool hasIterator() const;
903 void *begin(void *container) const;
904 void *end(void *container) const;
905 void destroyIterator(const void *iterator) const;
906 bool compareIterator(const void *i, const void *j) const;
907 void copyIterator(void *target, const void *source) const;
908 void advanceIterator(void *iterator, qsizetype step) const;
909 qsizetype diffIterator(const void *i, const void *j) const;
910
911 bool hasConstIterator() const;
912 void *constBegin(const void *container) const;
913 void *constEnd(const void *container) const;
914 void destroyConstIterator(const void *iterator) const;
915 bool compareConstIterator(const void *i, const void *j) const;
916 void copyConstIterator(void *target, const void *source) const;
917 void advanceConstIterator(void *iterator, qsizetype step) const;
918 qsizetype diffConstIterator(const void *i, const void *j) const;
919
920protected:
921 const QtMetaContainerPrivate::QMetaContainerInterface *d_ptr = nullptr;
922};
923
924class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
925{
926public:
927 QMetaSequence() = default;
928 explicit QMetaSequence(const QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
929
930 template<typename T>
931 static constexpr QMetaSequence fromContainer()
932 {
933 return QMetaSequence(&MetaSequence<T>::value);
934 }
935
936 QMetaType valueMetaType() const;
937
938 bool isSortable() const;
939 bool canAddValueAtBegin() const;
940 void addValueAtBegin(void *container, const void *value) const;
941 bool canAddValueAtEnd() const;
942 void addValueAtEnd(void *container, const void *value) const;
943 bool canRemoveValueAtBegin() const;
944 void removeValueAtBegin(void *container) const;
945 bool canRemoveValueAtEnd() const;
946 void removeValueAtEnd(void *container) const;
947
948 bool canGetValueAtIndex() const;
949 void valueAtIndex(const void *container, qsizetype index, void *result) const;
950
951 bool canSetValueAtIndex() const;
952 void setValueAtIndex(void *container, qsizetype index, const void *value) const;
953
954 bool canAddValue() const;
955 void addValue(void *container, const void *value) const;
956
957 bool canRemoveValue() const;
958 void removeValue(void *container) const;
959
960 bool canGetValueAtIterator() const;
961 void valueAtIterator(const void *iterator, void *result) const;
962
963 bool canSetValueAtIterator() const;
964 void setValueAtIterator(const void *iterator, const void *value) const;
965
966 bool canInsertValueAtIterator() const;
967 void insertValueAtIterator(void *container, const void *iterator, const void *value) const;
968
969 bool canEraseValueAtIterator() const;
970 void eraseValueAtIterator(void *container, const void *iterator) const;
971
972 bool canEraseRangeAtIterator() const;
973 void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
974
975 bool canGetValueAtConstIterator() const;
976 void valueAtConstIterator(const void *iterator, void *result) const;
977
978 friend bool operator==(const QMetaSequence &a, const QMetaSequence &b)
979 {
980 return a.d() == b.d();
981 }
982 friend bool operator!=(const QMetaSequence &a, const QMetaSequence &b)
983 {
984 return a.d() != b.d();
985 }
986
987 const QtMetaContainerPrivate::QMetaSequenceInterface *iface() const { return d(); }
988
989private:
990 template<typename T>
991 struct MetaSequence
992 {
993 static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value
994 = QtMetaContainerPrivate::QMetaSequenceInterface(
995 QtMetaContainerPrivate::QMetaSequenceForContainer<T>());
996 };
997
998 const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
999 {
1000 return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
1001 }
1002};
1003
1004class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
1005{
1006public:
1007 QMetaAssociation() = default;
1008 explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
1009
1010 template<typename T>
1011 static constexpr QMetaAssociation fromContainer()
1012 {
1013 return QMetaAssociation(&MetaAssociation<T>::value);
1014 }
1015
1016 QMetaType keyMetaType() const;
1017 QMetaType mappedMetaType() const;
1018
1019 bool canInsertKey() const
1020 {
1021 if (auto iface = d())
1022 return iface->insertKeyFn;
1023 return false;
1024 }
1025 void insertKey(void *container, const void *key) const
1026 {
1027 if (canInsertKey())
1028 d()->insertKeyFn(container, key);
1029 }
1030
1031 bool canRemoveKey() const
1032 {
1033 if (auto iface = d())
1034 return iface->removeKeyFn;
1035 return false;
1036 }
1037 void removeKey(void *container, const void *key) const
1038 {
1039 if (canRemoveKey())
1040 d()->removeKeyFn(container, key);
1041 }
1042
1043 bool canContainsKey() const
1044 {
1045 if (auto iface = d())
1046 return iface->containsKeyFn;
1047 return false;
1048 }
1049 bool containsKey(const void *container, const void *key) const
1050 {
1051 if (canContainsKey())
1052 return d()->containsKeyFn(container, key);
1053 return false;
1054 }
1055
1056
1057 bool canGetMappedAtKey() const
1058 {
1059 if (auto iface = d())
1060 return iface->mappedAtKeyFn;
1061 return false;
1062 }
1063 void mappedAtKey(const void *container, const void *key, void *mapped) const
1064 {
1065 if (canGetMappedAtKey())
1066 d()->mappedAtKeyFn(container, key, mapped);
1067 }
1068
1069 bool canSetMappedAtKey() const
1070 {
1071 if (auto iface = d())
1072 return iface->setMappedAtKeyFn;
1073 return false;
1074 }
1075 void setMappedAtKey(void *container, const void *key, const void *mapped) const
1076 {
1077 if (canSetMappedAtKey())
1078 d()->setMappedAtKeyFn(container, key, mapped);
1079 }
1080
1081 bool canGetKeyAtIterator() const
1082 {
1083 if (auto iface = d())
1084 return iface->keyAtIteratorFn;
1085 return false;
1086 }
1087
1088 void keyAtIterator(const void *iterator, void *key) const
1089 {
1090 if (canGetKeyAtIterator())
1091 d()->keyAtIteratorFn(iterator, key);
1092 }
1093
1094 bool canGetKeyAtConstIterator() const
1095 {
1096 if (auto iface = d())
1097 return iface->keyAtConstIteratorFn;
1098 return false;
1099 }
1100
1101 void keyAtConstIterator(const void *iterator, void *key) const
1102 {
1103 if (canGetKeyAtConstIterator())
1104 d()->keyAtConstIteratorFn(iterator, key);
1105 }
1106
1107 bool canGetMappedAtIterator() const
1108 {
1109 if (auto iface = d())
1110 return iface->mappedAtIteratorFn;
1111 return false;
1112 }
1113
1114 void mappedAtIterator(const void *iterator, void *mapped) const
1115 {
1116 if (canGetMappedAtIterator())
1117 d()->mappedAtIteratorFn(iterator, mapped);
1118 }
1119
1120 bool canGetMappedAtConstIterator() const
1121 {
1122 if (auto iface = d())
1123 return iface->mappedAtConstIteratorFn;
1124 return false;
1125 }
1126
1127 void mappedAtConstIterator(const void *iterator, void *mapped) const
1128 {
1129 if (canGetMappedAtConstIterator())
1130 d()->mappedAtConstIteratorFn(iterator, mapped);
1131 }
1132
1133 bool canSetMappedAtIterator() const
1134 {
1135 if (auto iface = d())
1136 return iface->setMappedAtIteratorFn;
1137 return false;
1138 }
1139
1140 void setMappedAtIterator(const void *iterator, const void *mapped) const
1141 {
1142 if (canSetMappedAtIterator())
1143 d()->setMappedAtIteratorFn(iterator, mapped);
1144 }
1145
1146 bool canCreateIteratorAtKey() const
1147 {
1148 if (auto iface = d())
1149 return iface->createIteratorAtKeyFn;
1150 return false;
1151 }
1152
1153 void *createIteratorAtKey(void *container, const void *key) const
1154 {
1155 if (canCreateIteratorAtKey())
1156 return d()->createIteratorAtKeyFn(container, key);
1157 return nullptr;
1158 }
1159
1160 bool canCreateConstIteratorAtKey() const
1161 {
1162 if (auto iface = d())
1163 return iface->createConstIteratorAtKeyFn;
1164 return false;
1165 }
1166
1167 void *createConstIteratorAtKey(const void *container, const void *key) const
1168 {
1169 if (canCreateConstIteratorAtKey())
1170 return d()->createConstIteratorAtKeyFn(container, key);
1171 return nullptr;
1172 }
1173
1174 friend bool operator==(const QMetaAssociation &a, const QMetaAssociation &b)
1175 {
1176 return a.d() == b.d();
1177 }
1178 friend bool operator!=(const QMetaAssociation &a, const QMetaAssociation &b)
1179 {
1180 return a.d() != b.d();
1181 }
1182
1183 const QtMetaContainerPrivate::QMetaAssociationInterface *iface() const { return d(); }
1184
1185private:
1186 template<typename T>
1187 struct MetaAssociation
1188 {
1189 static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value
1190 = QtMetaContainerPrivate::QMetaAssociationInterface(
1191 QtMetaContainerPrivate::QMetaAssociationForContainer<T>());
1192 };
1193
1194 const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
1195 {
1196 return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
1197 }
1198};
1199
1200QT_END_NAMESPACE
1201
1202#endif // QMETACONTAINER_H
1203

source code of qtbase/src/corelib/kernel/qmetacontainer.h