From a1898f4466518bf3e1b6e9154eec05ecf9d909e3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 8 Sep 2013 12:08:22 +0200 Subject: 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 --- .../snippets/code/src_corelib_kernel_qmetatype.cpp | 31 +++++++ src/corelib/kernel/qmetatype.cpp | 65 ++++++------- src/corelib/kernel/qmetatype.h | 102 +++++++-------------- 3 files changed, 98 insertions(+), 100 deletions(-) (limited to 'src/corelib') 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(); // compile error if MyStruct not declared typedef QString CustomString; qRegisterMetaType("CustomString"); //! [9] + +//! [10] + +#include + +Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::deque) + +void someFunc() +{ + std::deque container; + QVariant var = QVariant::fromValue(container); + // ... +} + +//! [10] + +//! [11] + +#include + +Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::unordered_map) + +void someFunc() +{ + std::unordered_map 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 @@ -140,6 +140,40 @@ struct DefinedTypesFilter { \sa qRegisterMetaType() */ +/*! + \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 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 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 @@ -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::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 \ - struct IsSequentialContainer > \ - { \ - 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 struct IsAssociativeContainer { enum { Value = false }; }; -#define QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(CONTAINER) \ - template \ - struct IsAssociativeContainer > \ - { \ - enum { Value = true }; \ - }; - QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QHash) - QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(QMap) - QT_DEFINE_ASSOCIATIVE_CONTAINER_TYPE(std::map) - - template::Value> struct SequentialContainerConverterHelper { @@ -1763,6 +1742,13 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE > \ return newId; \ } \ }; \ +namespace QtPrivate { \ +template \ +struct IsSequentialContainer > \ +{ \ + enum { Value = true }; \ +}; \ +} \ QT_END_NAMESPACE #define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \ @@ -1851,7 +1837,7 @@ struct QMetaTypeId< SMART_POINTER > \ };\ QT_END_NAMESPACE -#define Q_DECLARE_METATYPE_TEMPLATE_1ARG_ITER(TEMPLATENAME) \ +#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \ QT_BEGIN_NAMESPACE \ template 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 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 \ + struct IsAssociativeContainer > \ + { \ + 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::registerConverter(int id) return true; } - -#ifndef Q_QDOC -template -#endif -bool qRegisterSequentialConverter() -{ - Q_STATIC_ASSERT_X(QMetaTypeId2::Defined, - "The value_type of a sequential container must itself be a metatype."); - const int id = qMetaTypeId(); - const int toId = qMetaTypeId(); - if (QMetaType::hasRegisteredConverterFunction(id, toId)) - return true; - - static const QtMetaTypePrivate::QSequentialIterableConvertFunctor o; - static const QtPrivate::ConverterFunctor > f(o); - return QMetaType::registerConverterFunction(&f, id, toId); -} - -template -bool qRegisterAssociativeConverter() -{ - Q_STATIC_ASSERT_X(QMetaTypeId2::Defined - && QMetaTypeId2::Defined, - "The key_type and mapped_type of an associative container must themselves be metatypes."); - - const int id = qMetaTypeId(); - const int toId = qMetaTypeId(); - if (QMetaType::hasRegisteredConverterFunction(id, toId)) - return true; - static const QtMetaTypePrivate::QAssociativeIterableConvertFunctor o; - static const QtPrivate::ConverterFunctor > f(o); - - return QMetaType::registerConverterFunction(&f, id, toId); -} - QT_END_NAMESPACE #endif // QMETATYPE_H -- cgit v1.2.3