summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp31
-rw-r--r--src/corelib/kernel/qmetatype.cpp65
-rw-r--r--src/corelib/kernel/qmetatype.h102
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp28
4 files changed, 113 insertions, 113 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
index 4437313f0a..cb1346f74c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp
@@ -112,3 +112,34 @@ id = qMetaTypeId<MyStruct>(); // compile error if MyStruct not declared
typedef QString CustomString;
qRegisterMetaType<CustomString>("CustomString");
//! [9]
+
+//! [10]
+
+#include <deque>
+
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::deque)
+
+void someFunc()
+{
+ std::deque<QFile*> container;
+ QVariant var = QVariant::fromValue(container);
+ // ...
+}
+
+//! [10]
+
+//! [11]
+
+#include <unordered_list>
+
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::unordered_map)
+
+void someFunc()
+{
+ std::unordered_map<int, bool> container;
+ QVariant var = QVariant::fromValue(container);
+ // ...
+}
+
+//! [11]
+
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 17fbbda720..2ab6681bb9 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -141,6 +141,40 @@ struct DefinedTypesFilter {
*/
/*!
+ \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container)
+ \relates QMetaType
+
+ This macro makes the container \a Container known to QMetaType as a sequential
+ container. This makes it possible to put an instance of Container<T> into
+ a QVariant, if T itself is known to QMetaType.
+
+ Note that all of the Qt sequential containers already have built-in
+ support, and it is not necessary to use this macro with them. The
+ std::vector and std::list containers also have built-in support.
+
+ This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE():
+
+ \snippet code/src_corelib_kernel_qmetatype.cpp 10
+*/
+
+/*!
+ \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)
+ \relates QMetaType
+
+ This macro makes the container \a Container known to QMetaType as an associative
+ container. This makes it possible to put an instance of Container<T, U> into
+ a QVariant, if T and U are themselves known to QMetaType.
+
+ Note that all of the Qt associative containers already have built-in
+ support, and it is not necessary to use this macro with them. The
+ std::map container also has built-in support.
+
+ This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE():
+
+ \snippet code/src_corelib_kernel_qmetatype.cpp 11
+*/
+
+/*!
\enum QMetaType::Type
These are the built-in types supported by QMetaType:
@@ -2085,37 +2119,6 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
-/*!
- \fn bool qRegisterSequentialConverter()
- \relates QMetaType
- \since 5.2
-
- Registers a sequential container so that it can be converted to
- a QVariantList. If compilation fails, then you probably forgot to
- Q_DECLARE_METATYPE the value type.
-
- Note that it is not necessary to call this method for Qt containers (QList,
- QVector etc) or for std::vector or std::list. Such containers are automatically
- registered by Qt.
-
- \sa QVariant::canConvert()
-*/
-
-/*!
- \fn bool qRegisterAssociativeConverter()
- \relates QMetaType
- \since 5.2
-
- Registers an associative container so that it can be converted to
- a QVariantHash or QVariantMap. If the key_type and mapped_type of the container
- was not declared with Q_DECLARE_METATYPE(), compilation will fail.
-
- Note that it is not necessary to call this method for Qt containers (QHash,
- QMap etc) or for std::map. Such containers are automatically registered by Qt.
-
- \sa QVariant::canConvert()
-*/
-
namespace {
class TypeInfo {
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 6b1a988fce..bd4963e4f1 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1331,33 +1331,12 @@ namespace QtPrivate
enum { Value = false };
};
-#define QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(CONTAINER) \
- template<typename T> \
- struct IsSequentialContainer<CONTAINER<T> > \
- { \
- enum { Value = true }; \
- };
- QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE)
- QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::vector)
- QT_DEFINE_SEQUENTIAL_CONTAINER_TYPE(std::list)
-
template<typename T>
struct IsAssociativeContainer
{
enum { Value = false };
};
-#define QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(CONTAINER) \
- template<typename T, typename U> \
- struct IsAssociativeContainer<CONTAINER<T, U> > \
- { \
- enum { Value = true }; \
- };
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QHash)
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QMap)
- QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(std::map)
-
-
template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
struct SequentialContainerConverterHelper
{
@@ -1763,6 +1742,13 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
return newId; \
} \
}; \
+namespace QtPrivate { \
+template<typename T> \
+struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
+{ \
+ enum { Value = true }; \
+}; \
+} \
QT_END_NAMESPACE
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
@@ -1851,7 +1837,7 @@ struct QMetaTypeId< SMART_POINTER<T> > \
};\
QT_END_NAMESPACE
-#define Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER(TEMPLATENAME) \
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
QT_BEGIN_NAMESPACE \
template <class T> class TEMPLATENAME; \
QT_END_NAMESPACE \
@@ -1859,25 +1845,42 @@ QT_END_NAMESPACE
QT_END_NAMESPACE
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER)
+QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
+
+#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
-#undef Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
-Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::vector)
-Q_DECLARE_METATYPE_TEMPLATE_1ARG(std::list)
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
-#define Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
+#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
QT_BEGIN_NAMESPACE \
template <class T1, class T2> CPPTYPE TEMPLATENAME; \
QT_END_NAMESPACE \
- Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
+QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
+#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
+ QT_BEGIN_NAMESPACE \
+ namespace QtPrivate { \
+ template<typename T, typename U> \
+ struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
+ { \
+ enum { Value = true }; \
+ }; \
+ } \
+ QT_END_NAMESPACE \
+ Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
+
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
+
+Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair)
Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
-Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::map)
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
@@ -2009,45 +2012,6 @@ inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
return true;
}
-
-#ifndef Q_QDOC
-template<typename T>
-#endif
-bool qRegisterSequentialConverter()
-{
- Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::value_type>::Defined,
- "The value_type of a sequential container must itself be a metatype.");
- const int id = qMetaTypeId<T>();
- const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (QMetaType::hasRegisteredConverterFunction(id, toId))
- return true;
-
- static const QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QSequentialIterableImpl,
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
-}
-
-template<typename T>
-bool qRegisterAssociativeConverter()
-{
- Q_STATIC_ASSERT_X(QMetaTypeId2<typename T::key_type>::Defined
- && QMetaTypeId2<typename T::mapped_type>::Defined,
- "The key_type and mapped_type of an associative container must themselves be metatypes.");
-
- const int id = qMetaTypeId<T>();
- const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
- if (QMetaType::hasRegisteredConverterFunction(id, toId))
- return true;
- static const QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QAssociativeIterableImpl,
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
-
- return QMetaType::registerConverterFunction(&f, id, toId);
-}
-
QT_END_NAMESPACE
#endif // QMETATYPE_H
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index eab2ba4f36..a532407ad4 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -2278,23 +2278,26 @@ public:
template<typename T>
struct SequentialContainer
{
+ typedef T value_type;
+ typedef const T* const_iterator;
T t;
+ const_iterator begin() const { return &t; }
+ const_iterator end() const { return &t + 1; }
};
template<typename T, typename U>
-struct AssociativeContainer
+struct AssociativeContainer : public std::map<T, U>
{
- T t;
- U u;
};
}
Q_DECLARE_SMART_POINTER_METATYPE(MyNS::SmartPointer)
-Q_DECLARE_METATYPE_TEMPLATE_1ARG(MyNS::SequentialContainer)
-Q_DECLARE_METATYPE_TEMPLATE_2ARG(MyNS::AssociativeContainer)
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(MyNS::SequentialContainer)
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(MyNS::AssociativeContainer)
+// Test that explicit declaration does not degrade features.
Q_DECLARE_METATYPE(MyNS::SmartPointer<int>)
void tst_QVariant::qvariant_cast_QObject_wrapper()
@@ -2311,8 +2314,6 @@ void tst_QVariant::qvariant_cast_QObject_wrapper()
MyNS::SequentialContainer<int> sc;
sc.t = 47;
MyNS::AssociativeContainer<int, short> ac;
- ac.t = 42;
- ac.u = 5;
QVariant::fromValue(sc);
QVariant::fromValue(ac);
@@ -3538,9 +3539,11 @@ struct ContainerAPI<Container, QString>
#ifdef TEST_FORWARD_LIST
#include <forward_list>
+
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::forward_list)
+
+// Test that explicit declaration does not degrade features.
Q_DECLARE_METATYPE(std::forward_list<int>)
-Q_DECLARE_METATYPE(std::forward_list<QVariant>)
-Q_DECLARE_METATYPE(std::forward_list<QString>)
template<typename Value_Type>
struct ContainerAPI<std::forward_list<Value_Type> >
@@ -3624,6 +3627,9 @@ struct KeyGetter<std::map<T, U> >
#ifdef TEST_UNORDERED_MAP
#include <unordered_map>
typedef std::unordered_map<int, bool> StdUnorderedMap_int_bool;
+
+Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::unordered_map)
+
Q_DECLARE_METATYPE(StdUnorderedMap_int_bool)
template<typename T, typename U>
@@ -3718,9 +3724,6 @@ void tst_QVariant::iterateContainerElements()
TEST_SEQUENTIAL_ITERATION(std::list, QString)
#ifdef TEST_FORWARD_LIST
- qRegisterSequentialConverter<std::forward_list<int> >();
- qRegisterSequentialConverter<std::forward_list<QVariant> >();
- qRegisterSequentialConverter<std::forward_list<QString> >();
TEST_SEQUENTIAL_ITERATION(std::forward_list, int)
TEST_SEQUENTIAL_ITERATION(std::forward_list, QVariant)
TEST_SEQUENTIAL_ITERATION(std::forward_list, QString)
@@ -3758,7 +3761,6 @@ void tst_QVariant::iterateContainerElements()
TEST_ASSOCIATIVE_ITERATION(QMap, int, bool)
TEST_ASSOCIATIVE_ITERATION(std::map, int, bool)
#ifdef TEST_UNORDERED_MAP
- qRegisterAssociativeConverter<StdUnorderedMap_int_bool>();
TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool)
#endif
}