diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-12 16:25:31 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-18 09:54:19 +0100 |
commit | 6db55e3451e8ba244e9f2555713d44d988977871 (patch) | |
tree | 866b5475769d49a9a93cee483fc5ea6e6dfe6b87 /src | |
parent | 943cb0999dbbf1da99c1358b81ea3298ee116447 (diff) |
QSequentialIterable: Treat sets as appendable
QSet and std::(unordered_)set were so far not treated as appendable, as
they lack a push_back method. We do however need support for this in
declarative to enable converting back from QJSValue arrays to sets.
We achieve this by testing for and using the insert method. While vector
has also such a method, it doesn't take a single value, but rather a
position or iterator + value, so the template specialization is not
ambiguous.
Task-number: QTBUG-82743
Change-Id: I74fc7b1b856d9bcd38100b274ba2b69578ea8bbb
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 59ec8de0e9..7c22ff1693 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1014,6 +1014,24 @@ struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().p { static_cast<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); } }; +namespace QtPrivate { +namespace ContainerCapabilitiesMetaProgrammingHelper { + template<typename... Ts> + using void_t = void; +} +} + +template<typename Container> +struct ContainerCapabilitiesImpl<Container, QtPrivate::ContainerCapabilitiesMetaProgrammingHelper::void_t<decltype(std::declval<Container>().insert(std::declval<typename Container::value_type>())), decltype(std::declval<typename Container::value_type>() == std::declval<typename Container::value_type>())>> +{ + enum {ContainerCapabilities = ContainerIsAppendable}; + + // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl + // pointed to a const object to begin with + static void appendImpl(const void *container, const void *value) + { static_cast<Container *>(const_cast<void *>(container))->insert(*static_cast<const typename Container::value_type *>(value)); } +}; + template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category> struct CapabilitiesImpl; |