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