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 QMetaContainer
11 \inmodule QtCore
12 \since 6.0
13 \brief The QMetaContainer class provides common functionality for sequential
14 and associative containers.
15
16 QMetaContainer is part of Qt's meta-type system that allows type-erased access
17 to container-like types at runtime.
18
19 It serves as a common base for accessing properties of containers in a generic
20 way, such as size, iteration, and clearing operations, without knowing the actual
21 container type.
22
23 Derived classes, such as QMetaSequence, provide specialized interfaces for
24 sequential containers.
25
26 \ingroup objectmodel
27
28 \compares equality
29*/
30
31/*!
32 Returns \c true if the underlying container provides at least an input
33 iterator as defined by std::input_iterator_tag, otherwise returns
34 \c false. Forward, Bi-directional, and random access iterators are
35 specializations of input iterators. This method will also return
36 \c true if the container provides one of those.
37
38 QMetaContainer assumes that const and non-const iterators for the same
39 container have the same iterator traits.
40 */
41bool QMetaContainer::hasInputIterator() const
42{
43 if (!d_ptr)
44 return false;
45 return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::InputCapability);
46}
47
48/*!
49 Returns \c true if the underlying container provides at least a forward
50 iterator as defined by std::forward_iterator_tag, otherwise returns
51 \c false. Bi-directional iterators and random access iterators are
52 specializations of forward iterators. This method will also return
53 \c true if the container provides one of those.
54
55 QMetaContainer assumes that const and non-const iterators for the same
56 container have the same iterator traits.
57 */
58bool QMetaContainer::hasForwardIterator() const
59{
60 if (!d_ptr)
61 return false;
62 return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::ForwardCapability);
63}
64
65/*!
66 Returns \c true if the underlying container provides a bi-directional
67 iterator or a random access iterator as defined by
68 std::bidirectional_iterator_tag and std::random_access_iterator_tag,
69 respectively. Otherwise returns \c false.
70
71 QMetaContainer assumes that const and non-const iterators for the same
72 container have the same iterator traits.
73 */
74bool QMetaContainer::hasBidirectionalIterator() const
75{
76 if (!d_ptr)
77 return false;
78 return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::BiDirectionalCapability);
79}
80
81/*!
82 Returns \c true if the underlying container provides a random access
83 iterator as defined by std::random_access_iterator_tag, otherwise returns
84 \c false.
85
86 QMetaContainer assumes that const and non-const iterators for the same
87 container have the same iterator traits.
88 */
89bool QMetaContainer::hasRandomAccessIterator() const
90{
91 if (!d_ptr)
92 return false;
93 return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::RandomAccessCapability);
94}
95
96/*!
97 Returns \c true if the container can be queried for its size, \c false
98 otherwise.
99
100 \sa size()
101 */
102bool QMetaContainer::hasSize() const
103{
104 return d_ptr && d_ptr->sizeFn;
105}
106
107/*!
108 Returns the number of values in the given \a container if it can be
109 queried for its size. Otherwise returns \c -1.
110
111 \sa hasSize()
112 */
113qsizetype QMetaContainer::size(const void *container) const
114{
115 return hasSize() ? d_ptr->sizeFn(container) : -1;
116}
117
118/*!
119 Returns \c true if the container can be cleared, \c false otherwise.
120
121 \sa clear()
122 */
123bool QMetaContainer::canClear() const
124{
125 return d_ptr && d_ptr->clearFn;
126}
127
128/*!
129 Clears the given \a container if it can be cleared.
130
131 \sa canClear()
132 */
133void QMetaContainer::clear(void *container) const
134{
135 if (canClear())
136 d_ptr->clearFn(container);
137}
138
139/*!
140 Returns \c true if the underlying container offers a non-const iterator,
141 \c false otherwise.
142
143 \sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
144 advanceIterator(), copyIterator()
145 */
146bool QMetaContainer::hasIterator() const
147{
148 if (!d_ptr || !d_ptr->createIteratorFn)
149 return false;
150 Q_ASSERT(d_ptr->destroyIteratorFn);
151 Q_ASSERT(d_ptr->compareIteratorFn);
152 Q_ASSERT(d_ptr->copyIteratorFn);
153 Q_ASSERT(d_ptr->advanceIteratorFn);
154 Q_ASSERT(d_ptr->diffIteratorFn);
155 return true;
156}
157
158/*!
159 Creates and returns a non-const iterator pointing to the beginning of
160 \a container. The iterator is allocated on the heap using new. It has to be
161 destroyed using \l destroyIterator eventually, to reclaim the memory.
162
163 Returns \c nullptr if the container doesn't offer any non-const iterators.
164
165 \sa end(), constBegin(), constEnd(), destroyIterator()
166 */
167void *QMetaContainer::begin(void *container) const
168{
169 return hasIterator()
170 ? d_ptr->createIteratorFn(
171 container, QtMetaContainerPrivate::QMetaContainerInterface::AtBegin)
172 : nullptr;
173}
174
175/*!
176 Creates and returns a non-const iterator pointing to the end of
177 \a container. The iterator is allocated on the heap using new. It has to be
178 destroyed using \l destroyIterator eventually, to reclaim the memory.
179
180 Returns \c nullptr if the container doesn't offer any non-const iterators.
181
182 \sa hasIterator(), begin(), constBegin(), constEnd(), destroyIterator()
183 */
184void *QMetaContainer::end(void *container) const
185{
186 return hasIterator()
187 ? d_ptr->createIteratorFn(
188 container, QtMetaContainerPrivate::QMetaContainerInterface::AtEnd)
189 : nullptr;
190}
191
192/*!
193 Destroys a non-const \a iterator previously created using \l begin() or
194 \l end().
195
196 \sa begin(), end(), destroyConstIterator()
197 */
198void QMetaContainer::destroyIterator(const void *iterator) const
199{
200 if (hasIterator())
201 d_ptr->destroyIteratorFn(iterator);
202}
203
204/*!
205 Returns \c true if the non-const iterators \a i and \a j point to the same
206 value in the container they are iterating over, otherwise returns \c
207 false.
208
209 \sa begin(), end()
210 */
211bool QMetaContainer::compareIterator(const void *i, const void *j) const
212{
213 return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
214}
215
216/*!
217 Copies the non-const iterator \a source into the non-const iterator
218 \a target. Afterwards compareIterator(target, source) returns \c true.
219
220 \sa begin(), end()
221 */
222void QMetaContainer::copyIterator(void *target, const void *source) const
223{
224 if (hasIterator())
225 d_ptr->copyIteratorFn(target, source);
226}
227
228/*!
229 Advances the non-const \a iterator by \a step steps. If \a step is negative
230 the \a iterator is moved backwards, towards the beginning of the container.
231 The behavior is unspecified for negative values of \a step if
232 \l hasBidirectionalIterator() returns false.
233
234 \sa begin(), end()
235 */
236void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
237{
238 if (hasIterator())
239 d_ptr->advanceIteratorFn(iterator, step);
240}
241
242/*!
243 Returns the distance between the non-const iterators \a i and \a j, the
244 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
245 than \a i, the returned value is negative. The behavior is unspecified in
246 this case if \l hasBidirectionalIterator() returns false.
247
248 \sa begin(), end()
249 */
250qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
251{
252 return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
253}
254
255/*!
256 Returns \c true if the underlying container offers a const iterator,
257 \c false otherwise.
258
259 \sa constBegin(), constEnd(), destroyConstIterator(),
260 compareConstIterator(), diffConstIterator(), advanceConstIterator(),
261 copyConstIterator()
262 */
263bool QMetaContainer::hasConstIterator() const
264{
265 if (!d_ptr || !d_ptr->createConstIteratorFn)
266 return false;
267 Q_ASSERT(d_ptr->destroyConstIteratorFn);
268 Q_ASSERT(d_ptr->compareConstIteratorFn);
269 Q_ASSERT(d_ptr->copyConstIteratorFn);
270 Q_ASSERT(d_ptr->advanceConstIteratorFn);
271 Q_ASSERT(d_ptr->diffConstIteratorFn);
272 return true;
273}
274
275/*!
276 Creates and returns a const iterator pointing to the beginning of
277 \a container. The iterator is allocated on the heap using new. It has to be
278 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
279
280 Returns \c nullptr if the container doesn't offer any const iterators.
281
282 \sa constEnd(), begin(), end(), destroyConstIterator()
283 */
284void *QMetaContainer::constBegin(const void *container) const
285{
286 return hasConstIterator()
287 ? d_ptr->createConstIteratorFn(
288 container, QtMetaContainerPrivate::QMetaContainerInterface::AtBegin)
289 : nullptr;
290}
291
292/*!
293 Creates and returns a const iterator pointing to the end of
294 \a container. The iterator is allocated on the heap using new. It has to be
295 destroyed using \l destroyConstIterator eventually, to reclaim the memory.
296
297 Returns \c nullptr if the container doesn't offer any const iterators.
298
299 \sa constBegin(), begin(), end(), destroyConstIterator()
300 */
301void *QMetaContainer::constEnd(const void *container) const
302{
303 return hasConstIterator()
304 ? d_ptr->createConstIteratorFn(
305 container, QtMetaContainerPrivate::QMetaContainerInterface::AtEnd)
306 : nullptr;
307}
308
309/*!
310 Destroys a const \a iterator previously created using \l constBegin() or
311 \l constEnd().
312
313 \sa constBegin(), constEnd(), destroyIterator()
314 */
315void QMetaContainer::destroyConstIterator(const void *iterator) const
316{
317 if (hasConstIterator())
318 d_ptr->destroyConstIteratorFn(iterator);
319}
320
321/*!
322 Returns \c true if the const iterators \a i and \a j point to the same
323 value in the container they are iterating over, otherwise returns \c
324 false.
325
326 \sa constBegin(), constEnd()
327 */
328bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
329{
330 return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
331}
332
333/*!
334 Copies the const iterator \a source into the const iterator
335 \a target. Afterwards compareConstIterator(target, source) returns \c true.
336
337 \sa constBegin(), constEnd()
338 */
339void QMetaContainer::copyConstIterator(void *target, const void *source) const
340{
341 if (hasConstIterator())
342 d_ptr->copyConstIteratorFn(target, source);
343}
344
345/*!
346 Advances the const \a iterator by \a step steps. If \a step is negative
347 the \a iterator is moved backwards, towards the beginning of the container.
348 The behavior is unspecified for negative values of \a step if
349 \l hasBidirectionalIterator() returns false.
350
351 \sa constBegin(), constEnd()
352 */
353void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
354{
355 if (hasConstIterator())
356 d_ptr->advanceConstIteratorFn(iterator, step);
357}
358
359/*!
360 Returns the distance between the const iterators \a i and \a j, the
361 equivalent of \a i \c - \a j. If \a j is closer to the end of the container
362 than \a i, the returned value is negative. The behavior is unspecified in
363 this case if \l hasBidirectionalIterator() returns false.
364
365 \sa constBegin(), constEnd()
366 */
367qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
368{
369 return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
370}
371
372QT_END_NAMESPACE
Combined button and popup list for selecting options.