summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2016-12-01 12:24:42 +0100
committerEike Ziller <eike.ziller@qt.io>2016-12-01 11:36:12 +0000
commitc269cc1c6d9c5635ebfa9de3e8c8f8941bee542f (patch)
tree94840d6540014b3de14c4dcf9e05772a974d2322
parent6b0495d997c40a2326a5f9700ec41d57395dde06 (diff)
downloadqt-creator-c269cc1c6d9c5635ebfa9de3e8c8f8941bee542f.tar.gz
Revert "Revert "Revert "Algorithms: Simplify Utils::transform implementation"""
This reverts commit defb18aef413f0c9c99f957ebdd3bf1f8e2134e8. This reverts commit 602f8e72be21f9d1c68375a9e877b2e8524916cf. The refactoring of transform does not compile with MSVC2015 Update 2. Retry when we can upgrade to update 3. Change-Id: I8bfd6ad12c71759af4840c2615d9a8f2390fd4bc Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r--src/libs/utils/algorithm.h126
1 files changed, 80 insertions, 46 deletions
diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h
index 10b6daef94..76645e3311 100644
--- a/src/libs/utils/algorithm.h
+++ b/src/libs/utils/algorithm.h
@@ -214,78 +214,112 @@ using decay_t = typename std::decay<T>::type;
template<typename T>
using result_of_t = typename std::result_of<T>::type;
-// Result type of transform operation
-
-template<template<typename> class Container, template<typename> class InputContainer, typename IT, typename Function>
-using ResultContainer = Container<decay_t<result_of_t<Function(IT)>>>;
+// abstraction to treat Container<T> and QStringList similarly
+template<typename T>
+struct ContainerType
+{
-} // anonymous
+};
-// different container types for input and output, e.g. transforming a QList into a QSet
-template<template<typename> class C, // result container type
- template<typename> class SC, // input container type
- typename T, // input value type
- typename F> // function type
-Q_REQUIRED_RESULT
-auto transform(const SC<T> &container, F function) -> ResultContainer<C, SC, T, F>
+// specialization for qt container T_Container<T_Type>
+template<template<typename> class T_Container, typename T_Type>
+struct ContainerType<T_Container<T_Type>>
{
- ResultContainer<C, SC, T, F> result;
- std::transform(container.begin(), container.end(),
- inserter(result),
- function);
- return result;
-}
+ template<class F, template<typename> class C = T_Container>
+ using ResultOfTransform = C<decay_t<result_of_t<F (T_Type)>>>;
-// different container types for input and output, e.g. transforming a QList into a QSet
-// for member function pointers
-template<template<typename> class C, // result container type
- template<typename> class SC, // input container type
- typename T, // input value type
- typename R,
- typename S>
-Q_REQUIRED_RESULT
-auto transform(const SC<T> &container, R (S::*p)() const) -> ResultContainer<C, SC, T, R(S::*)() const>
+ template<class R>
+ using ResultOfTransformPMF = T_Container<decay_t<R>>;
+};
+
+// specialization for QStringList
+template<>
+struct ContainerType<QStringList> : ContainerType<QList<QString>>
{
- return Utils::transform<C, SC, T>(container, std::mem_fn(p));
+};
+
}
+// actual implementation of transform
+template<typename C, // result container type
+ typename SC> // input container type
+struct TransformImpl {
+ template <typename F>
+ Q_REQUIRED_RESULT
+ static C call(const SC &container, F function)
+ {
+ C result;
+ std::transform(container.begin(), container.end(),
+ inserter(result),
+ function);
+ return result;
+ }
+
+ template <typename R, typename S>
+ Q_REQUIRED_RESULT
+ static C call(const SC &container, R (S::*p)() const)
+ {
+ return call(container, std::mem_fn(p));
+ }
+
+};
+
// same container type for input and output, e.g. transforming a QList<QString> into QList<int>
// or QStringList -> QList<>
-template<template<typename> class C, // container
- typename T, // container value type
+template<typename C, // container
typename F>
Q_REQUIRED_RESULT
-auto transform(const C<T> &container, F function) -> ResultContainer<C, C, T, F>
+auto transform(const C &container, F function)
+-> typename ContainerType<C>::template ResultOfTransform<F>
{
- return Utils::transform<C, C, T>(container, function);
+ return TransformImpl<
+ typename ContainerType<C>::template ResultOfTransform<F>,
+ C
+ >::call(container, function);
}
// same container type for member function pointer
-template<template<typename> class C, // container
- typename T, // container value type
- typename R,
- typename S>
+template<typename C,
+ typename R,
+ typename S>
Q_REQUIRED_RESULT
-auto transform(const C<T> &container, R (S::*p)() const) -> ResultContainer<C, C, T, R(S::*)() const>
+auto transform(const C &container, R (S::*p)() const)
+ ->typename ContainerType<C>::template ResultOfTransformPMF<R>
{
- return Utils::transform<C, C, T>(container, std::mem_fn(p));
+ return TransformImpl<
+ typename ContainerType<C>::template ResultOfTransformPMF<R>,
+ C
+ >::call(container, p);
}
-// QStringList different containers
+// different container types for input and output, e.g. transforming a QList into a QSet
template<template<typename> class C, // result container type
- typename F>
+ typename SC, // input container type
+ typename F> // function type
Q_REQUIRED_RESULT
-auto transform(const QStringList &container, F function) -> ResultContainer<C, QList, QString, F>
+auto transform(const SC &container, F function)
+ -> typename ContainerType<SC>::template ResultOfTransform<F, C>
{
- return Utils::transform<C, QList, QString>(container, function);
+ return TransformImpl<
+ typename ContainerType<SC>::template ResultOfTransform<F, C>,
+ SC
+ >::call(container, function);
}
-// QStringList -> QList
-template<typename F>
+// different container types for input and output, e.g. transforming a QList into a QSet
+// for member function pointers
+template<template<typename> class C, // result container type
+ typename SC, // input container type
+ typename R,
+ typename S>
Q_REQUIRED_RESULT
-auto transform(const QStringList &container, F function) -> ResultContainer<QList, QList, QString, F>
+auto transform(const SC &container, R (S::*p)() const)
+ -> C<decay_t<R>>
{
- return Utils::transform<QList, QList, QString>(container, function);
+ return TransformImpl<
+ C<decay_t<R>>,
+ SC
+ >::call(container, p);
}
//////////////////