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#include "qmetacontainer.h"
5#include "qmetatype.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 \class QMetaSequence
11 \inmodule QtCore
12 \since 6.0
13 \brief The QMetaSequence class allows type erased access to sequential containers.
14
15 \ingroup objectmodel
16
17 The class provides a number of primitive container operations, using void*
18 as operands. This way, you can manipulate a generic container retrieved from
19 a Variant without knowing its type.
20
21 The void* arguments to the various methods are typically created by using
22 a \l QVariant of the respective container or value type, and calling
23 its \l QVariant::data() or \l QVariant::constData() methods. However, you
24 can also pass plain pointers to objects of the container or value type.
25
26 Iterator invalidation follows the rules given by the underlying containers
27 and is not expressed in the API. Therefore, for a truly generic container,
28 any iterators should be considered invalid after any write operation.
29*/
30
31/*!
32 \fn template<typename C> QMetaSequence QMetaSequence::fromContainer()
33 \since 6.0
34
35 Returns the QMetaSequence corresponding to the type given as template parameter.
36*/
37
38/*!
39 Returns \c true if the underlying container provides at least an input
40 iterator as defined by std::input_iterator_tag, otherwise returns
41 \c false. Forward, Bi-directional, and random access iterators are
42 specializations of input iterators. This method will also return
43 \c true if the container provides one of those.
44
45 QMetaSequence assumes that const and non-const iterators for the same
46 container have the same iterator traits.
47 */
48bool QMetaContainer::hasInputIterator() const
49{
50 if (!d_ptr)
51 return false;
52 return d_ptr->iteratorCapabilities.testAnyFlag(flag: QtMetaContainerPrivate::InputCapability);
53}
54
55/*!
56 Returns \c true if the underlying container provides at least a forward
57 iterator as defined by std::forward_iterator_tag, otherwise returns
58 \c false. Bi-directional iterators and random access iterators are
59 specializations of forward iterators. This method will also return
60 \c true if the container provides one of those.
61
62 QMetaSequence assumes that const and non-const iterators for the same
63 container have the same iterator traits.
64 */
65bool QMetaContainer::hasForwardIterator() const
66{
67 if (!d_ptr)
68 return false;
69 return d_ptr->iteratorCapabilities.testAnyFlag(flag: QtMetaContainerPrivate::ForwardCapability);
70}
71
72/*!
73 Returns \c true if the underlying container provides a bi-directional
74 iterator or a random access iterator as defined by
75 std::bidirectional_iterator_tag and std::random_access_iterator_tag,
76 respectively. Otherwise returns \c false.
77
78 QMetaSequence assumes that const and non-const iterators for the same
79 container have the same iterator traits.
80 */
81bool QMetaContainer::hasBidirectionalIterator() const
82{
83 if (!d_ptr)
84 return false;
85 return d_ptr->iteratorCapabilities.testAnyFlag(flag: QtMetaContainerPrivate::BiDirectionalCapability);
86}
87
88/*!
89 Returns \c true if the underlying container provides a random access
90 iterator as defined by std::random_access_iterator_tag, otherwise returns
91 \c false.
92
93 QMetaSequence assumes that const and non-const iterators for the same
94 container have the same iterator traits.
95 */
96bool QMetaContainer::hasRandomAccessIterator() const
97{
98 if (!d_ptr)
99 return false;
100 return d_ptr->iteratorCapabilities.testAnyFlag(flag: QtMetaContainerPrivate::RandomAccessCapability);
101}
102
103/*!
104 Returns the meta type for values stored in the container.
105 */
106QMetaType QMetaSequence::valueMetaType() const
107{
108 if (auto iface = d())
109 return QMetaType(iface->valueMetaType);
110 return QMetaType();
111}
112
113/*!
114 Returns \c true if the underlying container is sortable, otherwise returns
115 \c false. A container is considered sortable if values added to it are
116 placed in a defined location. Inserting into or adding to a sortable
117 container will always succeed. Inserting into or adding to an unsortable
118 container may not succeed, for example if the container is a QSet that
119 already contains the value being inserted.
120
121 \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
122 canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
123 */
124bool QMetaSequence::isSortable() const
125{
126 if (auto iface = d()) {
127 return (iface->addRemoveCapabilities
128 & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
129 && (iface->addRemoveCapabilities
130 & (QtMetaContainerPrivate::CanRemoveAtBegin
131 | QtMetaContainerPrivate::CanRemoveAtEnd));
132 }
133 return false;
134}
135
136/*!
137 Returns \c true if values added using \l addValue() can be placed at the
138 beginning of the container, otherwise returns \c false.
139
140 \sa addValueAtBegin(), canAddValueAtEnd()
141 */
142bool QMetaSequence::canAddValueAtBegin() const
143{
144 if (auto iface = d()) {
145 return iface->addValueFn
146 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
147 }
148 return false;
149}
150
151/*!
152 Adds \a value to the beginning of \a container if possible. If
153 \l canAddValueAtBegin() returns \c false, the \a value is not added.
154
155 \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
156 */
157void QMetaSequence::addValueAtBegin(void *container, const void *value) const
158{
159 if (canAddValueAtBegin())
160 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
161}
162
163/*!
164 Returns \c true if values can be removed from the beginning of the container
165 using \l removeValue() can be placed at the, otherwise returns \c false.
166
167 \sa removeValueAtBegin(), canRemoveValueAtEnd()
168 */
169bool QMetaSequence::canRemoveValueAtBegin() const
170{
171 if (auto iface = d()) {
172 return iface->removeValueFn
173 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
174 }
175 return false;
176}
177
178/*!
179 Removes a value from the beginning of \a container if possible. If
180 \l canRemoveValueAtBegin() returns \c false, the value is not removed.
181
182 \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
183 */
184void QMetaSequence::removeValueAtBegin(void *container) const
185{
186 if (canRemoveValueAtBegin())
187 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
188}
189
190/*!
191 Returns \c true if values added using \l addValue() can be placed at the
192 end of the container, otherwise returns \c false.
193
194 \sa addValueAtEnd(), canAddValueAtBegin()
195 */
196bool QMetaSequence::canAddValueAtEnd() const
197{
198 if (auto iface = d()) {
199 return iface->addValueFn
200 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
201 }
202 return false;
203}
204
205/*!
206 Adds \a value to the end of \a container if possible. If
207 \l canAddValueAtEnd() returns \c false, the \a value is not added.
208
209 \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
210 */
211void QMetaSequence::addValueAtEnd(void *container, const void *value) const
212{
213 if (canAddValueAtEnd())
214 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
215}
216
217/*!
218 Returns \c true if values can be removed from the end of the container
219 using \l removeValue() can be placed at the, otherwise returns \c false.
220
221 \sa removeValueAtEnd(), canRemoveValueAtBegin()
222 */
223bool QMetaSequence::canRemoveValueAtEnd() const
224{
225 if (auto iface = d()) {
226 return iface->removeValueFn
227 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
228 }
229 return false;
230}
231
232/*!
233 Removes a value from the end of \a container if possible. If
234 \l canRemoveValueAtEnd() returns \c false, the value is not removed.
235
236 \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
237 */
238void QMetaSequence::removeValueAtEnd(void *container) const
239{
240 if (canRemoveValueAtEnd())
241 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
242}
243
244/*!
245 Returns \c true if the container can be queried for its size, \c false
246 otherwise.
247
248 \sa size()
249 */
250bool QMetaContainer::hasSize() const
251{
252 return d_ptr && d_ptr->sizeFn;
253}
254
255/*!
256 Returns the number of values in the given \a container if it can be
257 queried for its size. Otherwise returns \c -1.
258
259 \sa hasSize()
260 */
261qsizetype QMetaContainer::size(const void *container) const
262{
263 return hasSize() ? d_ptr->sizeFn(container) : -1;
264}
265
266/*!
267 Returns \c true if the container can be cleared, \c false otherwise.
268
269 \sa clear()
270 */
271bool QMetaContainer::canClear() const
272{
273 return d_ptr && d_ptr->clearFn;
274}
275
276/*!
277 Clears the given \a container if it can be cleared.
278
279 \sa canClear()
280 */
281void QMetaContainer::clear(void *container) const
282{
283 if (canClear())
284 d_ptr->clearFn(container);
285}
286
287/*!
288 Returns \c true if values can be retrieved from the container by index,
289 otherwise \c false.
290
291 \sa valueAtIndex()
292 */
293bool QMetaSequence::canGetValueAtIndex() const
294{
295 if (auto iface = d())
296 return iface->valueAtIndexFn;
297 return false;
298}
299
300/*!
301 Retrieves the value at \a index in the \a container and places it in the
302 memory location pointed to by \a result, if that is possible.
303
304 \sa canGetValueAtIndex()
305 */
306void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
307{
308 if (canGetValueAtIndex())
309 d()->valueAtIndexFn(container, index, result);
310}
311
312/*!
313 Returns \c true if an value can be written to the container by index,
314 otherwise \c false.
315
316 \sa setValueAtIndex()
317*/
318bool QMetaSequence::canSetValueAtIndex() const
319{
320 if (auto iface = d())
321 return iface->setValueAtIndexFn;
322 return false;
323}
324
325/*!
326 Overwrites the value at \a index in the \a container using the \a value
327 passed as parameter if that is possible.
328
329 \sa canSetValueAtIndex()
330 */
331void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
332{
333 if (canSetValueAtIndex())
334 d()->setValueAtIndexFn(container, index, value);
335}
336
337/*!
338 Returns \c true if values can be added to the container, \c false
339 otherwise.
340
341 \sa addValue(), isSortable()
342 */
343bool QMetaSequence::canAddValue() const
344{
345 if (auto iface = d())
346 return iface->addValueFn;
347 return false;
348}
349
350/*!
351 Adds \a value to the \a container if possible. If \l canAddValue()
352 returns \c false, the \a value is not added. Else, if
353 \l canAddValueAtEnd() returns \c true, the \a value is added
354 to the end of the \a container. Else, if
355 \l canAddValueAtBegin() returns \c true, the \a value is added to
356 the beginning of the container. Else, the value is added in an unspecified
357 place or not at all. The latter is the case for adding values to an
358 unordered container, for example \l QSet.
359
360 \sa canAddValue(), canAddValueAtBegin(),
361 canAddValueAtEnd(), isSortable(), removeValue()
362 */
363void QMetaSequence::addValue(void *container, const void *value) const
364{
365 if (canAddValue()) {
366 d()->addValueFn(container, value,
367 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
368 }
369}
370
371/*!
372 Returns \c true if values can be removed from the container, \c false
373 otherwise.
374
375 \sa removeValue(), isSortable()
376 */
377bool QMetaSequence::canRemoveValue() const
378{
379 if (auto iface = d())
380 return iface->removeValueFn;
381 return false;
382}
383
384/*!
385 Removes an value from the \a container if possible. If
386 \l canRemoveValue() returns \c false, no value is removed. Else, if
387 \l canRemoveValueAtEnd() returns \c true, the last value in
388 the \a container is removed. Else, if \l canRemoveValueAtBegin()
389 returns \c true, the first value in the \a container is removed. Else,
390 an unspecified value or nothing is removed.
391
392 \sa canRemoveValue(), canRemoveValueAtBegin(),
393 canRemoveValueAtEnd(), isSortable(), addValue()
394 */
395void QMetaSequence::removeValue(void *container) const
396{
397 if (canRemoveValue()) {
398 d()->removeValueFn(container,
399 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
400 }
401}
402
403/*!
404 Returns \c true if the underlying container offers a non-const iterator,
405 \c false otherwise.
406
407 \sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
408 advanceIterator(), copyIterator()
409 */
410bool QMetaContainer::hasIterator() const
411{
412 if (!d_ptr || !d_ptr->createIteratorFn)
413 return false;
414 Q_ASSERT(d_ptr->destroyIteratorFn);
415 Q_ASSERT(d_ptr->compareIteratorFn);
416 Q_ASSERT(d_ptr->copyIteratorFn);
417 Q_ASSERT(d_ptr->advanceIteratorFn);
418 Q_ASSERT(d_ptr->diffIteratorFn);
419 return true;
420}
421
422/*!
423 Creates and returns a non-const iterator pointing to the beginning of
424 \a container. The iterator is allocated on the heap using new. It has to be
425 destroyed using \l destroyIterator eventually, to reclaim the memory.
426
427 Returns \c nullptr if the container doesn't offer any non-const iterators.
428
429 \sa end(), constBegin(), constEnd(), destroyIterator()
430 */
431void *QMetaContainer::begin(void *container) const
432{
433 return hasIterator()
434 ? d_ptr->createIteratorFn(
435 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
436 : nullptr;
437}
438
439/*!
440 Creates and returns a non-const iterator pointing to the end of
441 \a container. The iterator is allocated on the heap using new. It has to be
442 destroyed using \l destroyIterator eventually, to reclaim the memory.
443
444 Returns \c nullptr if the container doesn't offer any non-const iterators.
445
446 \sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
447 */
448void *QMetaContainer::end(void *container) const
449{
450 return hasIterator()
451 ? d_ptr->createIteratorFn(
452 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
453 : nullptr;
454}
455
456/*!
457 Destroys a non-const \a iterator previously created using \l begin() or
458 \l end().
459
460 \sa begin(), end(), destroyConstIterator()
461 */
462void QMetaContainer::destroyIterator(const void *iterator) const
463{
464 if (hasIterator())
465 d_ptr->destroyIteratorFn(iterator);
466}
467
468/*!
469 Returns \c true if the non-const iterators \a i and \a j point to the same
470 value in the container they are iterating over, otherwise returns \c
471 false.
472
473 \sa begin(), end()
474 */
475bool QMetaContainer::compareIterator(const void *i, const void *j) const
476{
477 return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
478}
479
480/*!
481 Copies the non-const iterator \a source into the non-const iterator
482 \a target. Afterwards compareIterator(target, source) returns \c true.
483
484 \sa begin(), end()
485 */
486void QMetaContainer::copyIterator(void *target, const void *source) const
487{
488 if (hasIterator())
489 d_ptr->copyIteratorFn(target, source);
490}
491
492/*!
493 Advances the non-const \a iterator by \a step steps. If \a steps is negative
494 the \a iterator is moved backwards, towards the beginning of the container.
495 The behavior is unspecified for negative values of \a step if
496 \l hasBidirectionalIterator() returns false.
497
498 \sa begin(), end()
499 */
500void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
501{
502 if (hasIterator())
503 d_ptr->advanceIteratorFn(iterator, step);
504}
505
506/*!
507 Returns the distance between the non-const iterators \a i and \a j, the
508 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
509 than \a i, the returned value is negative. The behavior is unspecified in
510 this case if \l hasBidirectionalIterator() returns false.
511
512 \sa begin(), end()
513 */
514qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
515{
516 return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
517}
518
519/*!
520 Returns \c true if the underlying container can retrieve the value pointed
521 to by a non-const iterator, \c false otherwise.
522
523 \sa hasIterator(), valueAtIterator()
524 */
525bool QMetaSequence::canGetValueAtIterator() const
526{
527 if (auto iface = d())
528 return iface->valueAtIteratorFn;
529 return false;
530}
531
532/*!
533 Retrieves the value pointed to by the non-const \a iterator and stores it
534 in the memory location pointed to by \a result, if possible.
535
536 \sa canGetValueAtIterator(), begin(), end()
537 */
538void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
539{
540 if (canGetValueAtIterator())
541 d()->valueAtIteratorFn(iterator, result);
542}
543
544/*!
545 Returns \c true if the underlying container can write to the value pointed
546 to by a non-const iterator, \c false otherwise.
547
548 \sa hasIterator(), setValueAtIterator()
549 */
550bool QMetaSequence::canSetValueAtIterator() const
551{
552 if (auto iface = d())
553 return iface->setValueAtIteratorFn;
554 return false;
555}
556
557/*!
558 Writes \a value to the value pointed to by the non-const \a iterator, if
559 possible.
560
561 \sa canSetValueAtIterator(), begin(), end()
562 */
563void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
564{
565 if (canSetValueAtIterator())
566 d()->setValueAtIteratorFn(iterator, value);
567}
568
569/*!
570 Returns \c true if the underlying container can insert a new value, taking
571 the location pointed to by a non-const iterator into account.
572
573 \sa hasIterator(), insertValueAtIterator()
574 */
575bool QMetaSequence::canInsertValueAtIterator() const
576{
577 if (auto iface = d())
578 return iface->insertValueAtIteratorFn;
579 return false;
580}
581
582/*!
583 Inserts \a value into the \a container, if possible, taking the non-const
584 \a iterator into account. If \l canInsertValueAtIterator() returns
585 \c false, the \a value is not inserted. Else if \l isSortable() returns
586 \c true, the value is inserted before the value pointed to by
587 \a iterator. Else, the \a value is inserted at an unspecified place or not
588 at all. In the latter case, the \a iterator is taken as a hint. If it points
589 to the correct place for the \a value, the operation may be faster than a
590 \l addValue() without iterator.
591
592 \sa canInsertValueAtIterator(), isSortable(), begin(), end()
593 */
594void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
595 const void *value) const
596{
597 if (canInsertValueAtIterator())
598 d()->insertValueAtIteratorFn(container, iterator, value);
599}
600
601/*!
602 Returns \c true if the value pointed to by a non-const iterator can be
603 erased, \c false otherwise.
604
605 \sa hasIterator(), eraseValueAtIterator()
606 */
607bool QMetaSequence::canEraseValueAtIterator() const
608{
609 if (auto iface = d())
610 return iface->eraseValueAtIteratorFn;
611 return false;
612}
613
614/*!
615 Erases the value pointed to by the non-const \a iterator from the
616 \a container, if possible.
617
618 \sa canEraseValueAtIterator(), begin(), end()
619 */
620void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
621{
622 if (canEraseValueAtIterator())
623 d()->eraseValueAtIteratorFn(container, iterator);
624}
625
626/*!
627 Returns \c true if a range between two iterators can be erased from the
628 container, \c false otherwise.
629 */
630bool QMetaSequence::canEraseRangeAtIterator() const
631{
632 if (auto iface = d())
633 return iface->eraseRangeAtIteratorFn;
634 return false;
635}
636
637/*!
638 Erases the range of values between the iterators \a iterator1 and
639 \a iterator2 from the \a container, if possible.
640
641 \sa canEraseValueAtIterator(), begin(), end()
642 */
643void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
644 const void *iterator2) const
645{
646 if (canEraseRangeAtIterator())
647 d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
648}
649
650/*!
651 Returns \c true if the underlying container offers a const iterator,
652 \c false otherwise.
653
654 \sa constBegin(), constEnd(), destroyConstIterator(),
655 compareConstIterator(), diffConstIterator(), advanceConstIterator(),
656 copyConstIterator()
657 */
658bool QMetaContainer::hasConstIterator() const
659{
660 if (!d_ptr || !d_ptr->createConstIteratorFn)
661 return false;
662 Q_ASSERT(d_ptr->destroyConstIteratorFn);
663 Q_ASSERT(d_ptr->compareConstIteratorFn);
664 Q_ASSERT(d_ptr->copyConstIteratorFn);
665 Q_ASSERT(d_ptr->advanceConstIteratorFn);
666 Q_ASSERT(d_ptr->diffConstIteratorFn);
667 return true;
668}
669
670/*!
671 Creates and returns a const iterator pointing to the beginning of
672 \a container. The iterator is allocated on the heap using new. It has to be
673 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
674
675 Returns \c nullptr if the container doesn't offer any const iterators.
676
677 \sa constEnd(), begin(), end(), destroyConstIterator()
678 */
679void *QMetaContainer::constBegin(const void *container) const
680{
681 return hasConstIterator()
682 ? d_ptr->createConstIteratorFn(
683 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
684 : nullptr;
685}
686
687/*!
688 Creates and returns a const iterator pointing to the end of
689 \a container. The iterator is allocated on the heap using new. It has to be
690 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
691
692 Returns \c nullptr if the container doesn't offer any const iterators.
693
694 \sa constBegin(), begin(), end(), destroyConstIterator()
695 */
696void *QMetaContainer::constEnd(const void *container) const
697{
698 return hasConstIterator()
699 ? d_ptr->createConstIteratorFn(
700 container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
701 : nullptr;
702}
703
704/*!
705 Destroys a const \a iterator previously created using \l constBegin() or
706 \l constEnd().
707
708 \sa constBegin(), constEnd(), destroyIterator()
709 */
710void QMetaContainer::destroyConstIterator(const void *iterator) const
711{
712 if (hasConstIterator())
713 d_ptr->destroyConstIteratorFn(iterator);
714}
715
716/*!
717 Returns \c true if the const iterators \a i and \a j point to the same
718 value in the container they are iterating over, otherwise returns \c
719 false.
720
721 \sa constBegin(), constEnd()
722 */
723bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
724{
725 return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
726}
727
728/*!
729 Copies the const iterator \a source into the const iterator
730 \a target. Afterwards compareConstIterator(target, source) returns \c true.
731
732 \sa constBegin(), constEnd()
733 */
734void QMetaContainer::copyConstIterator(void *target, const void *source) const
735{
736 if (hasConstIterator())
737 d_ptr->copyConstIteratorFn(target, source);
738}
739
740/*!
741 Advances the const \a iterator by \a step steps. If \a steps is negative
742 the \a iterator is moved backwards, towards the beginning of the container.
743 The behavior is unspecified for negative values of \a step if
744 \l hasBidirectionalIterator() returns false.
745
746 \sa constBegin(), constEnd()
747 */
748void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
749{
750 if (hasConstIterator())
751 d_ptr->advanceConstIteratorFn(iterator, step);
752}
753
754/*!
755 Returns the distance between the const iterators \a i and \a j, the
756 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
757 than \a i, the returned value is negative. The behavior is unspecified in
758 this case if \l hasBidirectionalIterator() returns false.
759
760 \sa constBegin(), constEnd()
761 */
762qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
763{
764 return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
765}
766
767/*!
768 Returns \c true if the underlying container can retrieve the value pointed
769 to by a const iterator, \c false otherwise.
770
771 \sa hasConstIterator(), valueAtConstIterator()
772 */
773bool QMetaSequence::canGetValueAtConstIterator() const
774{
775 if (auto iface = d())
776 return iface->valueAtConstIteratorFn;
777 return false;
778}
779
780/*!
781 Retrieves the value pointed to by the const \a iterator and stores it
782 in the memory location pointed to by \a result, if possible.
783
784 \sa canGetValueAtConstIterator(), constBegin(), constEnd()
785 */
786void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
787{
788 if (canGetValueAtConstIterator())
789 d()->valueAtConstIteratorFn(iterator, result);
790}
791
792/*!
793 \fn bool operator==(QMetaSequence a, QMetaSequence b)
794 \since 6.0
795 \relates QMetaSequence
796
797 Returns \c true if the QMetaSequence \a a represents the same container type
798 as the QMetaSequence \a b, otherwise returns \c false.
799*/
800
801/*!
802 \fn bool operator!=(QMetaSequence a, QMetaSequence b)
803 \since 6.0
804 \relates QMetaSequence
805
806 Returns \c true if the QMetaSequence \a a represents a different container
807 type than the QMetaSequence \a b, otherwise returns \c false.
808*/
809
810
811/*!
812 Returns the meta type for keys in the container.
813 */
814QMetaType QMetaAssociation::keyMetaType() const
815{
816 if (auto iface = d())
817 return QMetaType(iface->keyMetaType);
818 return QMetaType();
819}
820
821/*!
822 Returns the meta type for mapped values in the container.
823 */
824QMetaType QMetaAssociation::mappedMetaType() const
825{
826 if (auto iface = d())
827 return QMetaType(iface->mappedMetaType);
828 return QMetaType();
829}
830
831QT_END_NAMESPACE
832

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