From c269cc1c6d9c5635ebfa9de3e8c8f8941bee542f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 1 Dec 2016 12:24:42 +0100 Subject: [PATCH] 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 --- src/libs/utils/algorithm.h | 144 +++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 55 deletions(-) diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index 10b6daef94f..76645e3311a 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -214,78 +214,112 @@ using decay_t = typename std::decay::type; template using result_of_t = typename std::result_of::type; -// Result type of transform operation +// abstraction to treat Container and QStringList similarly +template +struct ContainerType +{ -template class Container, template class InputContainer, typename IT, typename Function> -using ResultContainer = Container>>; +}; -} // anonymous +// specialization for qt container T_Container +template class T_Container, typename T_Type> +struct ContainerType> +{ + template class C = T_Container> + using ResultOfTransform = C>>; + + template + using ResultOfTransformPMF = T_Container>; +}; + +// specialization for QStringList +template<> +struct ContainerType : ContainerType> +{ +}; + +} + +// actual implementation of transform +template // input container type +struct TransformImpl { + template + 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 + 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 into QList +// or QStringList -> QList<> +template +Q_REQUIRED_RESULT +auto transform(const C &container, F function) +-> typename ContainerType::template ResultOfTransform +{ + return TransformImpl< + typename ContainerType::template ResultOfTransform, + C + >::call(container, function); +} + +// same container type for member function pointer +template +Q_REQUIRED_RESULT +auto transform(const C &container, R (S::*p)() const) + ->typename ContainerType::template ResultOfTransformPMF +{ + return TransformImpl< + typename ContainerType::template ResultOfTransformPMF, + C + >::call(container, p); +} // different container types for input and output, e.g. transforming a QList into a QSet template class C, // result container type - template class SC, // input container type - typename T, // input value type + typename SC, // input container type typename F> // function type Q_REQUIRED_RESULT -auto transform(const SC &container, F function) -> ResultContainer +auto transform(const SC &container, F function) + -> typename ContainerType::template ResultOfTransform { - ResultContainer result; - std::transform(container.begin(), container.end(), - inserter(result), - function); - return result; + return TransformImpl< + typename ContainerType::template ResultOfTransform, + SC + >::call(container, function); } // different container types for input and output, e.g. transforming a QList into a QSet // for member function pointers template class C, // result container type - template class SC, // input container type - typename T, // input value type + typename SC, // input container type typename R, typename S> Q_REQUIRED_RESULT -auto transform(const SC &container, R (S::*p)() const) -> ResultContainer +auto transform(const SC &container, R (S::*p)() const) + -> C> { - return Utils::transform(container, std::mem_fn(p)); -} - -// same container type for input and output, e.g. transforming a QList into QList -// or QStringList -> QList<> -template class C, // container - typename T, // container value type - typename F> -Q_REQUIRED_RESULT -auto transform(const C &container, F function) -> ResultContainer -{ - return Utils::transform(container, function); -} - -// same container type for member function pointer -template class C, // container - typename T, // container value type - typename R, - typename S> -Q_REQUIRED_RESULT -auto transform(const C &container, R (S::*p)() const) -> ResultContainer -{ - return Utils::transform(container, std::mem_fn(p)); -} - -// QStringList different containers -template class C, // result container type - typename F> -Q_REQUIRED_RESULT -auto transform(const QStringList &container, F function) -> ResultContainer -{ - return Utils::transform(container, function); -} - -// QStringList -> QList -template -Q_REQUIRED_RESULT -auto transform(const QStringList &container, F function) -> ResultContainer -{ - return Utils::transform(container, function); + return TransformImpl< + C>, + SC + >::call(container, p); } //////////////////