diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2013-09-08 12:08:22 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-09 21:28:41 +0200 |
commit | a1898f4466518bf3e1b6e9154eec05ecf9d909e3 (patch) | |
tree | 7bd00c197258d89038aa9e03941e326d174571a9 | |
parent | 7fb3906d4e7cec7c69feee007b8393c9c2a3a316 (diff) |
Metatype: Remove the need for runtime-registration of 3rd party containers.
Replace that need with a macro so that registration of the
container helper conversions is done at the time of registration
of the container (usually when it is put into a QVariant).
Change-Id: I823fb3fdbce306ebc9f146675ac43724cec678d5
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_kernel_qmetatype.cpp | 31 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 65 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 102 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 28 |
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 } |