summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-03 13:41:39 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-12 09:12:26 +0200
commitef93fdeb098f78a0afe1df72c53ba26bf7a11c60 (patch)
tree4862c44b7013f5965ba6c888d1059d24dfb5d87a /src/corelib
parent73fe229eb434236402ec1685b1f17f96417001b9 (diff)
Provide methods for adding values to a sequential iterable
Provide functionality to add and remove values, so that you can use a sequential iterable as stack or queue if the underlying container supports this. To this end, provide a way to specify whether the value should be added or removed at the beginning or the end of the iterable. Change-Id: If63d302f3ca085e56d601116ce4dfaa6b94a0c4f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/kernel/qiterable.cpp67
-rw-r--r--src/corelib/kernel/qiterable.h10
-rw-r--r--src/corelib/kernel/qmetacontainer.cpp181
-rw-r--r--src/corelib/kernel/qmetacontainer.h138
4 files changed, 321 insertions, 75 deletions
diff --git a/src/corelib/kernel/qiterable.cpp b/src/corelib/kernel/qiterable.cpp
index dd7f194686..5aed1832af 100644
--- a/src/corelib/kernel/qiterable.cpp
+++ b/src/corelib/kernel/qiterable.cpp
@@ -134,6 +134,73 @@ qsizetype QSequentialIterable::size() const
}
/*!
+ * Adds \a value to the container, at \a position, if possible.
+ */
+void QSequentialIterable::addValue(const QVariant &value, Position position)
+{
+ QVariant converted;
+ const void *valuePtr;
+ if (valueMetaType() == QMetaType::fromType<QVariant>()) {
+ valuePtr = &value;
+ } else if (valueMetaType() == value.metaType()) {
+ valuePtr = value.constData();
+ } else if (value.canConvert(valueMetaType())) {
+ converted = value;
+ converted.convert(valueMetaType());
+ valuePtr = converted.constData();
+ } else {
+ converted = QVariant(valueMetaType());
+ valuePtr = converted.constData();
+ }
+
+ switch (position) {
+ case AtBegin:
+ if (metaSequence().canAddValueAtBegin())
+ metaSequence().addValueAtBegin(mutableIterable(), valuePtr);
+ break;
+ case AtEnd:
+ if (metaSequence().canAddValueAtEnd())
+ metaSequence().addValueAtEnd(mutableIterable(), valuePtr);
+ break;
+ case Unspecified:
+ if (metaSequence().canAddValue())
+ metaSequence().addValue(mutableIterable(), valuePtr);
+ break;
+ }
+}
+
+/*!
+ * Removes a value from the container, at \a position, if possible.
+ */
+void QSequentialIterable::removeValue(Position position)
+{
+ switch (position) {
+ case AtBegin:
+ if (metaSequence().canRemoveValueAtBegin())
+ metaSequence().removeValueAtBegin(mutableIterable());
+ break;
+ case AtEnd:
+ if (metaSequence().canRemoveValueAtEnd())
+ metaSequence().removeValueAtEnd(mutableIterable());
+ break;
+ case Unspecified:
+ if (metaSequence().canRemoveValue())
+ metaSequence().removeValue(mutableIterable());
+ break;
+ }
+}
+
+/*!
+ Returns whether it is possible to iterate over the container in forward
+ direction. This corresponds to the std::forward_iterator_tag iterator trait
+ of the iterator and const_iterator of the container.
+*/
+bool QSequentialIterable::canForwardIterate() const
+{
+ return m_metaSequence.hasForwardIterator();
+}
+
+/*!
Returns whether it is possible to iterate over the container in reverse. This
corresponds to the std::bidirectional_iterator_tag iterator trait of the
const_iterator of the container.
diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h
index a38fd8d184..ad13d971ec 100644
--- a/src/corelib/kernel/qiterable.h
+++ b/src/corelib/kernel/qiterable.h
@@ -163,10 +163,20 @@ public:
QVariant at(qsizetype idx) const;
qsizetype size() const;
+ enum Position { Unspecified, AtBegin, AtEnd };
+ void addValue(const QVariant &value, Position position = Unspecified);
+ void removeValue(Position position = Unspecified);
+
+ bool canForwardIterate() const;
bool canReverseIterate() const;
const void *constIterable() const { return m_iterable.constPointer(); }
+
+ // TODO: fix this when introducing mutable iterables
+ void *mutableIterable() { return const_cast<void *>(m_iterable.constPointer()); }
+
QMetaSequence metaSequence() const { return m_metaSequence; }
+ QMetaType valueMetaType() const { return m_metaSequence.valueMetaType(); }
};
namespace QtPrivate {
diff --git a/src/corelib/kernel/qmetacontainer.cpp b/src/corelib/kernel/qmetacontainer.cpp
index 77ac152508..e11381c1bd 100644
--- a/src/corelib/kernel/qmetacontainer.cpp
+++ b/src/corelib/kernel/qmetacontainer.cpp
@@ -144,51 +144,134 @@ QMetaType QMetaSequence::valueMetaType() const
}
/*!
- Returns \c true if the underlying container is ordered, otherwise returns
- \c false. A container is considered ordered if values added to it are
- placed in a defined location. Inserting into or adding to an ordered
- container will always succeed. Inserting into or adding to an unordered
+ Returns \c true if the underlying container is sortable, otherwise returns
+ \c false. A container is considered sortable if values added to it are
+ placed in a defined location. Inserting into or adding to a sortable
+ container will always succeed. Inserting into or adding to an unsortable
container may not succeed, for example if the container is a QSet that
already contains the value being inserted.
- \sa addValue(), insertValueAtIterator(), addsAndRemovesValuesAtBegin(),
- addsAndRemovesValuesAtEnd()
+ \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
+ canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
*/
-bool QMetaSequence::isOrdered() const
+bool QMetaSequence::isSortable() const
{
- if (!d_ptr)
- return false;
- return d_ptr->addRemovePosition != QtMetaContainerPrivate::QMetaSequenceInterface::Random;
+ if (d_ptr) {
+ return (d_ptr->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
+ && (d_ptr->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanRemoveAtBegin
+ | QtMetaContainerPrivate::CanRemoveAtEnd));
+ }
+ return false;
}
/*!
- Returns \c true if values added using \l addValue() are placed at the
- beginning of the container, otherwise returns \c false. Likewise
- \l removeValue() removes an value from the beginning of the container
- if this method returns \c true.
+ Returns \c true if values added using \l addValue() can be placed at the
+ beginning of the container, otherwise returns \c false.
- \sa addValue(), removeValue(), addsAndRemovesValuesAtEnd()
+ \sa addValueAtBegin(), canAddValueAtEnd()
*/
-bool QMetaSequence::addsAndRemovesValuesAtBegin() const
+bool QMetaSequence::canAddValueAtBegin() const
{
- if (!d_ptr)
- return false;
- return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin;
+ if (d_ptr) {
+ return d_ptr->addValueFn
+ && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
+ }
+ return false;
}
/*!
- Returns \c true if values added using \l addValue() are placed at the
- end of the container, otherwise returns \c false. Likewise
- \l removeValue() removes an value from the end of the container
- if this method returns \c true.
+ Adds \a value to the beginning of \a container if possible. If
+ \l canAddValueAtBegin() returns \c false, the \a value is not added.
- \sa addValue(), removeValue(), addsAndRemovesValuesAtBegin()
+ \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
*/
-bool QMetaSequence::addsAndRemovesValuesAtEnd() const
+void QMetaSequence::addValueAtBegin(void *container, const void *value) const
{
- if (!d_ptr)
- return false;
- return d_ptr->addRemovePosition == QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd;
+ if (canAddValueAtBegin())
+ d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values can be removed from the beginning of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtBegin(), canRemoveValueAtEnd()
+ */
+bool QMetaSequence::canRemoveValueAtBegin() const
+{
+ if (d_ptr) {
+ return d_ptr->removeValueFn
+ && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the beginning of \a container if possible. If
+ \l canRemoveValueAtBegin() returns \c false, the \a value is not removeed.
+
+ \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
+ */
+void QMetaSequence::removeValueAtBegin(void *container) const
+{
+ if (canRemoveValueAtBegin())
+ d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values added using \l addValue() can be placed at the
+ end of the container, otherwise returns \c false.
+
+ \sa addValueAtEnd(), canAddValueAtBegin()
+ */
+bool QMetaSequence::canAddValueAtEnd() const
+{
+ if (d_ptr) {
+ return d_ptr->addValueFn
+ && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Adds \a value to the end of \a container if possible. If
+ \l canAddValueAtEnd() returns \c false, the \a value is not added.
+
+ \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
+ */
+void QMetaSequence::addValueAtEnd(void *container, const void *value) const
+{
+ if (canAddValueAtEnd())
+ d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+}
+
+/*!
+ Returns \c true if values can be removed from the end of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtEnd(), canRemoveValueAtBegin()
+ */
+bool QMetaSequence::canRemoveValueAtEnd() const
+{
+ if (d_ptr) {
+ return d_ptr->removeValueFn
+ && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the end of \a container if possible. If
+ \l canRemoveValueAtEnd() returns \c false, the \a value is not removeed.
+
+ \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
+ */
+void QMetaSequence::removeValueAtEnd(void *container) const
+{
+ if (canRemoveValueAtEnd())
+ d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
}
/*!
@@ -284,7 +367,7 @@ void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void
Returns \c true if values can be added to the container, \c false
otherwise.
- \sa addValue(), isOrdered()
+ \sa addValue(), isSortable()
*/
bool QMetaSequence::canAddValue() const
{
@@ -294,27 +377,29 @@ bool QMetaSequence::canAddValue() const
/*!
Adds \a value to the \a container if possible. If \l canAddValue()
returns \c false, the \a value is not added. Else, if
- \l addsAndRemovesValuesAtBegin() returns \c true, the \a value is added
- to the beginning of the \a container. Else, if
- \l addsAndRemovesValuesAtEnd() returns \c true, the \a value is added to
- the end of the container. Else, the value is added in an unspecified
+ \l canAddValueAtEnd() returns \c true, the \a value is added
+ to the end of the \a container. Else, if
+ \l canAddValueAtBegin() returns \c true, the \a value is added to
+ the beginning of the container. Else, the value is added in an unspecified
place or not at all. The latter is the case for adding values to an
unordered container, for example \l QSet.
- \sa canAddValue(), addsAndRemovesValuesAtBegin(),
- addsAndRemovesValuesAtEnd(), isOrdered(), removeValue()
+ \sa canAddValue(), canAddValueAtBegin(),
+ canAddValueAtEnd(), isSortable(), removeValue()
*/
void QMetaSequence::addValue(void *container, const void *value) const
{
- if (canAddValue())
- d_ptr->addValueFn(container, value);
+ if (canAddValue()) {
+ d_ptr->addValueFn(container, value,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
}
/*!
Returns \c true if values can be removed from the container, \c false
otherwise.
- \sa removeValue(), isOrdered()
+ \sa removeValue(), isSortable()
*/
bool QMetaSequence::canRemoveValue() const
{
@@ -324,18 +409,20 @@ bool QMetaSequence::canRemoveValue() const
/*!
Removes an value from the \a container if possible. If
\l canRemoveValue() returns \c false, no value is removed. Else, if
- \l addsAndRemovesValuesAtBegin() returns \c true, the first value in
- the \a container is removed. Else, if \l addsAndRemovesValuesAtEnd()
- returns \c true, the last value in the \a container is removed. Else,
+ \l canRemoveValueAtEnd() returns \c true, the last value in
+ the \a container is removed. Else, if \l canRemoveValueAtBegin()
+ returns \c true, the first value in the \a container is removed. Else,
an unspecified value or nothing is removed.
- \sa canRemoveValue(), addsAndRemovesValuesAtBegin(),
- addsAndRemovesValuesAtEnd(), isOrdered(), addValue()
+ \sa canRemoveValue(), canRemoveValueAtBegin(),
+ canRemoveValueAtEnd(), isSortable(), addValue()
*/
void QMetaSequence::removeValue(void *container) const
{
- if (canRemoveValue())
- d_ptr->removeValueFn(container);
+ if (canRemoveValue()) {
+ d_ptr->removeValueFn(container,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
}
/*!
@@ -514,14 +601,14 @@ bool QMetaSequence::canInsertValueAtIterator() const
/*!
Inserts \a value into the \a container, if possible, taking the non-const
\a iterator into account. If \l canInsertValueAtIterator() returns
- \c false, the \a value is not inserted. Else if \l isOrdered() returns
+ \c false, the \a value is not inserted. Else if \l isSortable() returns
\c true, the value is inserted before the value pointed to by
\a iterator. Else, the \a value is inserted at an unspecified place or not
at all. In the latter case, the \a iterator is taken as a hint. If it points
to the correct place for the \a value, the operation may be faster than a
\l addValue() without iterator.
- \sa canInsertValueAtIterator(), isOrdered(), begin(), end()
+ \sa canInsertValueAtIterator(), isSortable(), begin(), end()
*/
void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
const void *value) const
diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h
index 1e2157951e..8c0d723f64 100644
--- a/src/corelib/kernel/qmetacontainer.h
+++ b/src/corelib/kernel/qmetacontainer.h
@@ -59,15 +59,24 @@ enum IteratorCapability : quint8 {
Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
+enum AddRemoveCapability : quint8 {
+ CanAddAtBegin = 1 << 0,
+ CanRemoveAtBegin = 1 << 1,
+ CanAddAtEnd = 1 << 2,
+ CanRemoveAtEnd = 1 << 3
+};
+Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
+Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
+
class QMetaSequenceInterface
{
public:
- enum Position : quint8 { AtBegin, AtEnd, Random };
+ enum Position : quint8 { AtBegin, AtEnd, Unspecified };
ushort revision;
IteratorCapabilities iteratorCapabilities;
- Position addRemovePosition;
QMetaType valueMetaType;
+ AddRemoveCapabilities addRemoveCapabilities;
using SizeFn = qsizetype(*)(const void *);
SizeFn sizeFn;
@@ -79,9 +88,9 @@ public:
using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
SetValueAtIndexFn setValueAtIndexFn;
- using AddValueFn = void(*)(void *, const void *);
+ using AddValueFn = void(*)(void *, const void *, Position);
AddValueFn addValueFn;
- using RemoveValueFn = void(*)(void *);
+ using RemoveValueFn = void(*)(void *, Position);
RemoveValueFn removeValueFn;
using CreateIteratorFn = void *(*)(void *, Position);
@@ -144,13 +153,18 @@ class QMetaSequenceForContainer
return {};
}
- static constexpr QMetaSequenceInterface::Position getAddRemovePosition()
+ static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
{
- if constexpr (QContainerTraits::has_push_back_v<C> && QContainerTraits::has_pop_back_v<C>)
- return QMetaSequenceInterface::AtEnd;
- if constexpr (QContainerTraits::has_push_front_v<C> && QContainerTraits::has_pop_front_v<C>)
- return QMetaSequenceInterface::AtBegin;
- return QMetaSequenceInterface::Random;
+ AddRemoveCapabilities caps;
+ if constexpr (QContainerTraits::has_push_back_v<C>)
+ caps |= CanAddAtEnd;
+ if constexpr (QContainerTraits::has_pop_back_v<C>)
+ caps |= CanRemoveAtEnd;
+ if constexpr (QContainerTraits::has_push_front_v<C>)
+ caps |= CanAddAtBegin;
+ if constexpr (QContainerTraits::has_pop_front_v<C>)
+ caps |= CanRemoveAtBegin;
+ return caps;
}
static constexpr QMetaType getValueMetaType()
@@ -208,19 +222,49 @@ class QMetaSequenceForContainer
static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
{
if constexpr (QContainerTraits::has_push_back_v<C>) {
- return [](void *c, const void *v) {
- static_cast<C *>(c)->push_back(
- *static_cast<const QContainerTraits::value_type<C> *>(v));
- };
+ if constexpr (QContainerTraits::has_push_front_v<C>) {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->push_front(value);
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->push_back(value);
+ break;
+ }
+ };
+ } else {
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->push_back(value);
+ break;
+ }
+ };
+ }
} else if constexpr (QContainerTraits::has_push_front_v<C>) {
- return [](void *c, const void *v) {
- static_cast<C *>(c)->push_front(
- *static_cast<const QContainerTraits::value_type<C> *>(v));
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ const auto &value = *static_cast<const QContainerTraits::value_type<C> *>(v);
+ switch (position) {
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->push_front(value);
+ case QMetaSequenceInterface::AtEnd:
+ break;
+ }
};
} else if constexpr (QContainerTraits::has_insert_v<C>) {
- return [](void *c, const void *v) {
- static_cast<C *>(c)->insert(
- *static_cast<const QContainerTraits::value_type<C> *>(v));
+ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
+ if (position == QMetaSequenceInterface::Unspecified) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerTraits::value_type<C> *>(v));
+ }
};
} else {
return nullptr;
@@ -230,9 +274,41 @@ class QMetaSequenceForContainer
static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
{
if constexpr (QContainerTraits::has_pop_back_v<C>) {
- return [](void *c) { static_cast<C *>(c)->pop_back(); };
+ if constexpr (QContainerTraits::has_pop_front_v<C>) {
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->pop_front();
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ case QMetaSequenceInterface::Unspecified:
+ static_cast<C *>(c)->pop_back();
+ break;
+ }
+ };
+ } else {
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::AtBegin:
+ break;
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtEnd:
+ static_cast<C *>(c)->pop_back();
+ break;
+ }
+ };
+ }
} else if constexpr (QContainerTraits::has_pop_front_v<C>) {
- return [](void *c) { static_cast<C *>(c)->pop_front(); };
+ return [](void *c, QMetaSequenceInterface::Position position) {
+ switch (position) {
+ case QMetaSequenceInterface::Unspecified:
+ case QMetaSequenceInterface::AtBegin:
+ static_cast<C *>(c)->pop_front();
+ break;
+ case QMetaSequenceInterface::AtEnd:
+ break;
+ }
+ };
} else {
return nullptr;
}
@@ -245,7 +321,7 @@ class QMetaSequenceForContainer
using Iterator = QContainerTraits::iterator<C>;
switch (p) {
case QMetaSequenceInterface::AtBegin:
- case QMetaSequenceInterface::Random:
+ case QMetaSequenceInterface::Unspecified:
return new Iterator(static_cast<C *>(c)->begin());
break;
case QMetaSequenceInterface::AtEnd:
@@ -377,7 +453,7 @@ class QMetaSequenceForContainer
using Iterator = QContainerTraits::const_iterator<C>;
switch (p) {
case QMetaSequenceInterface::AtBegin:
- case QMetaSequenceInterface::Random:
+ case QMetaSequenceInterface::Unspecified:
return new Iterator(static_cast<const C *>(c)->begin());
break;
case QMetaSequenceInterface::AtEnd:
@@ -471,8 +547,8 @@ template<typename C>
QMetaSequenceInterface QMetaSequenceForContainer<C>::metaSequence = {
/*.revision=*/ 0,
/*.iteratorCapabilities=*/ getIteratorCapabilities(),
- /*.addRemovePosition=*/ getAddRemovePosition(),
/*.valueMetaType=*/ getValueMetaType(),
+ /*.addRemoveCapabilities=*/ getAddRemoveCapabilities(),
/*.sizeFn=*/ getSizeFn(),
/*.clearFn=*/ getClearFn(),
/*.valueAtIndexFn=*/ getValueAtIndexFn(),
@@ -525,9 +601,15 @@ public:
QMetaType valueMetaType() const;
- bool isOrdered() const;
- bool addsAndRemovesValuesAtBegin() const;
- bool addsAndRemovesValuesAtEnd() const;
+ bool isSortable() const;
+ bool canAddValueAtBegin() const;
+ void addValueAtBegin(void *container, const void *value) const;
+ bool canAddValueAtEnd() const;
+ void addValueAtEnd(void *container, const void *value) const;
+ bool canRemoveValueAtBegin() const;
+ void removeValueAtBegin(void *container) const;
+ bool canRemoveValueAtEnd() const;
+ void removeValueAtEnd(void *container) const;
bool hasSize() const;
qsizetype size(const void *container) const;