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
qmetasequence.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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 <QtCore/qmetasequence.h>
5#include <QtCore/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 Returns the meta type for values stored in the container.
42 */
43QMetaType QMetaSequence::valueMetaType() const
44{
45 if (auto iface = d())
46 return QMetaType(iface->valueMetaType);
47 return QMetaType();
48}
49
50/*!
51 Returns \c true if the underlying container is sortable, otherwise returns
52 \c false. A container is considered sortable if values added to it are
53 placed in a defined location. Inserting into or adding to a sortable
54 container will always succeed. Inserting into or adding to an unsortable
55 container may not succeed, for example if the container is a QSet that
56 already contains the value being inserted.
57
58 \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
59 canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
60 */
61bool QMetaSequence::isSortable() const
62{
63 if (auto iface = d()) {
64 return (iface->addRemoveCapabilities
65 & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
66 && (iface->addRemoveCapabilities
67 & (QtMetaContainerPrivate::CanRemoveAtBegin
68 | QtMetaContainerPrivate::CanRemoveAtEnd));
69 }
70 return false;
71}
72
73/*!
74 Returns \c true if values added using \l addValue() can be placed at the
75 beginning of the container, otherwise returns \c false.
76
77 \sa addValueAtBegin(), canAddValueAtEnd()
78 */
79bool QMetaSequence::canAddValueAtBegin() const
80{
81 if (auto iface = d()) {
82 return iface->addValueFn
83 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
84 }
85 return false;
86}
87
88/*!
89 Adds \a value to the beginning of \a container if possible. If
90 \l canAddValueAtBegin() returns \c false, the \a value is not added.
91
92 \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
93 */
94void QMetaSequence::addValueAtBegin(void *container, const void *value) const
95{
96 if (canAddValueAtBegin())
97 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
98}
99
100/*!
101 Returns \c true if values can be removed from the beginning of the container
102 using \l removeValue(), otherwise returns \c false.
103
104 \sa removeValueAtBegin(), canRemoveValueAtEnd()
105 */
106bool QMetaSequence::canRemoveValueAtBegin() const
107{
108 if (auto iface = d()) {
109 return iface->removeValueFn
110 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
111 }
112 return false;
113}
114
115/*!
116 Removes a value from the beginning of \a container if possible. If
117 \l canRemoveValueAtBegin() returns \c false, the value is not removed.
118
119 \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
120 */
121void QMetaSequence::removeValueAtBegin(void *container) const
122{
123 if (canRemoveValueAtBegin())
124 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
125}
126
127/*!
128 Returns \c true if values added using \l addValue() can be placed at the
129 end of the container, otherwise returns \c false.
130
131 \sa addValueAtEnd(), canAddValueAtBegin()
132 */
133bool QMetaSequence::canAddValueAtEnd() const
134{
135 if (auto iface = d()) {
136 return iface->addValueFn
137 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
138 }
139 return false;
140}
141
142/*!
143 Adds \a value to the end of \a container if possible. If
144 \l canAddValueAtEnd() returns \c false, the \a value is not added.
145
146 \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
147 */
148void QMetaSequence::addValueAtEnd(void *container, const void *value) const
149{
150 if (canAddValueAtEnd())
151 d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
152}
153
154/*!
155 Returns \c true if values can be removed from the end of the container
156 using \l removeValue(), otherwise returns \c false.
157
158 \sa removeValueAtEnd(), canRemoveValueAtBegin()
159 */
160bool QMetaSequence::canRemoveValueAtEnd() const
161{
162 if (auto iface = d()) {
163 return iface->removeValueFn
164 && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
165 }
166 return false;
167}
168
169/*!
170 Removes a value from the end of \a container if possible. If
171 \l canRemoveValueAtEnd() returns \c false, the value is not removed.
172
173 \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
174 */
175void QMetaSequence::removeValueAtEnd(void *container) const
176{
177 if (canRemoveValueAtEnd())
178 d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
179}
180
181/*!
182 Returns \c true if values can be retrieved from the container by index,
183 otherwise \c false.
184
185 \sa valueAtIndex()
186 */
187bool QMetaSequence::canGetValueAtIndex() const
188{
189 if (auto iface = d())
190 return iface->valueAtIndexFn;
191 return false;
192}
193
194/*!
195 Retrieves the value at \a index in the \a container and places it in the
196 memory location pointed to by \a result, if that is possible.
197
198 \sa canGetValueAtIndex()
199 */
200void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
201{
202 if (canGetValueAtIndex())
203 d()->valueAtIndexFn(container, index, result);
204}
205
206/*!
207 Returns \c true if a value can be written to the container by index,
208 otherwise \c false.
209
210 \sa setValueAtIndex()
211*/
212bool QMetaSequence::canSetValueAtIndex() const
213{
214 if (auto iface = d())
215 return iface->setValueAtIndexFn;
216 return false;
217}
218
219/*!
220 Overwrites the value at \a index in the \a container using the \a value
221 passed as parameter if that is possible.
222
223 \sa canSetValueAtIndex()
224 */
225void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
226{
227 if (canSetValueAtIndex())
228 d()->setValueAtIndexFn(container, index, value);
229}
230
231/*!
232 Returns \c true if values can be added to the container, \c false
233 otherwise.
234
235 \sa addValue(), isSortable()
236 */
237bool QMetaSequence::canAddValue() const
238{
239 if (auto iface = d())
240 return iface->addValueFn;
241 return false;
242}
243
244/*!
245 Adds \a value to the \a container if possible. If \l canAddValue()
246 returns \c false, the \a value is not added. Else, if
247 \l canAddValueAtEnd() returns \c true, the \a value is added
248 to the end of the \a container. Else, if
249 \l canAddValueAtBegin() returns \c true, the \a value is added to
250 the beginning of the container. Else, the value is added in an unspecified
251 place or not at all. The latter is the case for adding values to an
252 unordered container, for example \l QSet.
253
254 \sa canAddValue(), canAddValueAtBegin(),
255 canAddValueAtEnd(), isSortable(), removeValue()
256 */
257void QMetaSequence::addValue(void *container, const void *value) const
258{
259 if (canAddValue()) {
260 d()->addValueFn(container, value,
261 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
262 }
263}
264
265/*!
266 Returns \c true if values can be removed from the container, \c false
267 otherwise.
268
269 \sa removeValue(), isSortable()
270 */
271bool QMetaSequence::canRemoveValue() const
272{
273 if (auto iface = d())
274 return iface->removeValueFn;
275 return false;
276}
277
278/*!
279 Removes a value from the \a container if possible. If
280 \l canRemoveValue() returns \c false, no value is removed. Else, if
281 \l canRemoveValueAtEnd() returns \c true, the last value in
282 the \a container is removed. Else, if \l canRemoveValueAtBegin()
283 returns \c true, the first value in the \a container is removed. Else,
284 an unspecified value or nothing is removed.
285
286 \sa canRemoveValue(), canRemoveValueAtBegin(),
287 canRemoveValueAtEnd(), isSortable(), addValue()
288 */
289void QMetaSequence::removeValue(void *container) const
290{
291 if (canRemoveValue()) {
292 d()->removeValueFn(container,
293 QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
294 }
295}
296
297
298/*!
299 Returns \c true if the underlying container can retrieve the value pointed
300 to by a non-const iterator, \c false otherwise.
301
302 \sa hasIterator(), valueAtIterator()
303 */
304bool QMetaSequence::canGetValueAtIterator() const
305{
306 if (auto iface = d())
307 return iface->valueAtIteratorFn;
308 return false;
309}
310
311/*!
312 Retrieves the value pointed to by the non-const \a iterator and stores it
313 in the memory location pointed to by \a result, if possible.
314
315 \sa canGetValueAtIterator(), begin(), end()
316 */
317void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
318{
319 if (canGetValueAtIterator())
320 d()->valueAtIteratorFn(iterator, result);
321}
322
323/*!
324 Returns \c true if the underlying container can write to the value pointed
325 to by a non-const iterator, \c false otherwise.
326
327 \sa hasIterator(), setValueAtIterator()
328 */
329bool QMetaSequence::canSetValueAtIterator() const
330{
331 if (auto iface = d())
332 return iface->setValueAtIteratorFn;
333 return false;
334}
335
336/*!
337 Writes \a value to the value pointed to by the non-const \a iterator, if
338 possible.
339
340 \sa canSetValueAtIterator(), begin(), end()
341 */
342void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
343{
344 if (canSetValueAtIterator())
345 d()->setValueAtIteratorFn(iterator, value);
346}
347
348/*!
349 Returns \c true if the underlying container can insert a new value, taking
350 the location pointed to by a non-const iterator into account.
351
352 \sa hasIterator(), insertValueAtIterator()
353 */
354bool QMetaSequence::canInsertValueAtIterator() const
355{
356 if (auto iface = d())
357 return iface->insertValueAtIteratorFn;
358 return false;
359}
360
361/*!
362 Inserts \a value into the \a container, if possible, taking the non-const
363 \a iterator into account. If \l canInsertValueAtIterator() returns
364 \c false, the \a value is not inserted. Else if \l isSortable() returns
365 \c true, the value is inserted before the value pointed to by
366 \a iterator. Else, the \a value is inserted at an unspecified place or not
367 at all. In the latter case, the \a iterator is taken as a hint. If it points
368 to the correct place for the \a value, the operation may be faster than a
369 \l addValue() without iterator.
370
371 \sa canInsertValueAtIterator(), isSortable(), begin(), end()
372 */
373void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
374 const void *value) const
375{
376 if (canInsertValueAtIterator())
377 d()->insertValueAtIteratorFn(container, iterator, value);
378}
379
380/*!
381 Returns \c true if the value pointed to by a non-const iterator can be
382 erased, \c false otherwise.
383
384 \sa hasIterator(), eraseValueAtIterator()
385 */
386bool QMetaSequence::canEraseValueAtIterator() const
387{
388 if (auto iface = d())
389 return iface->eraseValueAtIteratorFn;
390 return false;
391}
392
393/*!
394 Erases the value pointed to by the non-const \a iterator from the
395 \a container, if possible.
396
397 \sa canEraseValueAtIterator(), begin(), end()
398 */
399void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
400{
401 if (canEraseValueAtIterator())
402 d()->eraseValueAtIteratorFn(container, iterator);
403}
404
405/*!
406 Returns \c true if a range between two iterators can be erased from the
407 container, \c false otherwise.
408 */
409bool QMetaSequence::canEraseRangeAtIterator() const
410{
411 if (auto iface = d())
412 return iface->eraseRangeAtIteratorFn;
413 return false;
414}
415
416/*!
417 Erases the range of values between the iterators \a iterator1 and
418 \a iterator2 from the \a container, if possible.
419
420 \sa canEraseValueAtIterator(), begin(), end()
421 */
422void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
423 const void *iterator2) const
424{
425 if (canEraseRangeAtIterator())
426 d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
427}
428
429
430/*!
431 Returns \c true if the underlying container can retrieve the value pointed
432 to by a const iterator, \c false otherwise.
433
434 \sa hasConstIterator(), valueAtConstIterator()
435 */
436bool QMetaSequence::canGetValueAtConstIterator() const
437{
438 if (auto iface = d())
439 return iface->valueAtConstIteratorFn;
440 return false;
441}
442
443/*!
444 Retrieves the value pointed to by the const \a iterator and stores it
445 in the memory location pointed to by \a result, if possible.
446
447 \sa canGetValueAtConstIterator(), constBegin(), constEnd()
448 */
449void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
450{
451 if (canGetValueAtConstIterator())
452 d()->valueAtConstIteratorFn(iterator, result);
453}
454
455/*!
456 \fn bool QMetaSequence::operator==(const QMetaSequence &lhs, const QMetaSequence &rhs)
457 \since 6.0
458
459 Returns \c true if the QMetaSequence \a lhs represents the same container type
460 as the QMetaSequence \a rhs, otherwise returns \c false.
461*/
462
463/*!
464 \fn bool QMetaSequence::operator!=(const QMetaSequence &lhs, const QMetaSequence &rhs)
465 \since 6.0
466
467 Returns \c true if the QMetaSequence \a lhs represents a different container
468 type than the QMetaSequence \a rhs, otherwise returns \c false.
469*/
470
471/*!
472 \class QMetaSequence::Iterable
473 \inherits QIterable
474 \since 6.11
475 \inmodule QtCore
476 \brief The QMetaSequence::Iterable class is an iterable interface for a container in a QVariant.
477
478 This class allows several methods of accessing the values of a container
479 held within a QVariant. An instance of QMetaSequence::Iterable can be
480 extracted from a QVariant if it can be converted to a QVariantList, or if
481 the container it contains is registered using
482 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE. Most sequential containers found
483 in Qt and some found in the C++ standard library are automatically
484 registered.
485
486 \snippet code/src_corelib_kernel_qvariant.cpp 9
487
488 The container itself is not copied before iterating over it.
489
490 \sa QVariant
491*/
492
493/*!
494 \typealias QMetaSequence::Iterable::RandomAccessIterator
495 Exposes an iterator using std::random_access_iterator_tag.
496*/
497
498/*!
499 \typealias QMetaSequence::Iterable::BidirectionalIterator
500 Exposes an iterator using std::bidirectional_iterator_tag.
501*/
502
503/*!
504 \typealias QMetaSequence::Iterable::ForwardIterator
505 Exposes an iterator using std::forward_iterator_tag.
506*/
507
508/*!
509 \typealias QMetaSequence::Iterable::InputIterator
510 Exposes an iterator using std::input_iterator_tag.
511*/
512
513/*!
514 \typealias QMetaSequence::Iterable::RandomAccessConstIterator
515 Exposes a const_iterator using std::random_access_iterator_tag.
516*/
517
518/*!
519 \typealias QMetaSequence::Iterable::BidirectionalConstIterator
520 Exposes a const_iterator using std::bidirectional_iterator_tag.
521*/
522
523/*!
524 \typealias QMetaSequence::Iterable::ForwardConstIterator
525 Exposes a const_iterator using std::forward_iterator_tag.
526*/
527
528/*!
529 \typealias QMetaSequence::Iterable::InputConstIterator
530 Exposes a const_iterator using std::input_iterator_tag.
531*/
532
533/*!
534 \fn QVariant QMetaSequence::Iterable::at(qsizetype idx) const
535 Returns the value at position \a idx in the container.
536
537 \note If the underlying container does not provide a native way to retrieve
538 an element at an index, this method will synthesize the access using
539 iterators. This behavior is deprecated and will be removed in a future
540 version of Qt.
541*/
542
543/*!
544 \fn void QMetaSequence::Iterable::setAt(qsizetype idx, const QVariant &value)
545 Sets the element at position \a idx in the container to \a value.
546*/
547
548/*!
549 \class QMetaSequence::Iterable::ConstIterator
550 \inmodule QtCore
551 \inherits QConstIterator
552 \since 6.11
553 \brief QMetaSequence::Iterable::ConstIterator allows iteration over a container in a QVariant.
554
555 A QMetaSequence::Iterable::ConstIterator can only be created by a
556 QMetaSequence::Iterable instance, and can be used in a way similar to other
557 stl-style iterators.
558
559 \snippet code/src_corelib_kernel_qvariant.cpp 9
560*/
561
562/*!
563 \class QMetaSequence::Iterable::Iterator
564 \inmodule QtCore
565 \inherits QIterator
566 \since 6.11
567 \brief QMetaSequence::Iterable::Iterator allows iteration over a container in a QVariant.
568
569 A QMetaSequence::Iterable::Iterator can only be created by a QMetaSequence::Iterable
570 instance, and can be used in a way similar to other stl-style iterators.
571*/
572
573/*!
574 \fn QVariant::Reference<QMetaSequence::Iterable::Iterator> QMetaSequence::Iterable::Iterator::operator*() const
575 Returns the current item, converted to a QVariant::Reference.
576*/
577
578/*!
579 \fn QVariant::Pointer<QMetaSequence::Iterable::Iterator> QMetaSequence::Iterable::Iterator::operator->() const
580 Returns the current item, converted to a QVariant::Pointer.
581*/
582
583/*!
584 \fn QVariant::Reference<QMetaSequence::Iterable::Iterator> QMetaSequence::Iterable::Iterator::operator[](qsizetype n) const
585 Returns the item offset from the current one by \a n, converted to a
586 QVariant::Reference.
587*/
588
589/*!
590 \fn QVariant QMetaSequence::Iterable::ConstIterator::operator*() const
591 Returns the current item, converted to a QVariant.
592*/
593
594/*!
595 \fn QVariant::ConstPointer<QMetaSequence::Iterable::ConstIterator> QMetaSequence::Iterable::ConstIterator::operator->() const
596 Returns the current item, converted to a QVariant::ConstPointer.
597*/
598
599/*!
600 \fn QVariant QMetaSequence::Iterable::ConstIterator::operator[](qsizetype n) const
601 Returns the item offset from the current one by \a n, converted to a
602 QVariant.
603*/
604
605QT_END_NAMESPACE
\inmodule QtCore
Definition qmetatype.h:339