diff options
author | Eike Ziller <eike.ziller@qt.io> | 2016-12-01 12:24:42 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2016-12-01 11:36:12 +0000 |
commit | c269cc1c6d9c5635ebfa9de3e8c8f8941bee542f (patch) | |
tree | 94840d6540014b3de14c4dcf9e05772a974d2322 | |
parent | 6b0495d997c40a2326a5f9700ec41d57395dde06 (diff) | |
download | qt-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.h | 126 |
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); } ////////////////// |