Utils::transform; Remove some code duplication

Change-Id: Ic1237351f6d67cdd8a5d19500d833dce96b08f36
Reviewed-by: Nikita Baryshnikov <nib952051@gmail.com>
Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com>
This commit is contained in:
Daniel Teske
2015-08-10 18:41:04 +02:00
parent 0a23dd4e23
commit 9bcb933008

View File

@@ -150,11 +150,6 @@ auto equal(R S::*member, T value)
///////////////// /////////////////
namespace { namespace {
// needed for msvc 2010, that doesn't have a declval
// can be removed once we stop supporting it
template<typename T>
T &&declval();
///////////////// /////////////////
// helper code for transform to use back_inserter and thus push_back for everything // helper code for transform to use back_inserter and thus push_back for everything
// and insert for QSet<> // and insert for QSet<>
@@ -201,12 +196,9 @@ inserter(QSet<X> &container)
return QSetInsertIterator<QSet<X>>(container); return QSetInsertIterator<QSet<X>>(container);
} }
// helper: removes const, volatile and references from a type // decay_t is C++14, so provide it here, remove once we require C++14
template<typename T> template<typename T>
struct RemoveCvAndReference using decay_t = typename std::decay<T>::type;
{
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
};
// abstraction to treat Container<T> and QStringList similarly // abstraction to treat Container<T> and QStringList similarly
template<typename T> template<typename T>
@@ -225,19 +217,24 @@ struct ContainerType<T_Container<T_Type>> {
{ {
typedef T_Container<NewElementType> type; typedef T_Container<NewElementType> type;
}; };
template<class F, template<typename> class C = T_Container>
struct ResultOfTransform
{
typedef C<decay_t<typename std::result_of<F (ElementType)>::type>> type;
};
template<class R>
struct ResultOfTransformPMF
{
typedef typename WithElementType<decay_t<R>>::type type;
};
}; };
// specialization for QStringList // specialization for QStringList
template<> template<>
struct ContainerType<QStringList> struct ContainerType<QStringList> : ContainerType<QList<QString>>
{ {
typedef QString ElementType;
template<class NewElementType>
struct WithElementType
{
typedef QList<NewElementType> type;
};
}; };
} }
@@ -273,18 +270,10 @@ template<typename C, // container
typename F> typename F>
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
auto transform(const C &container, F function) auto transform(const C &container, F function)
-> typename ContainerType<C>::template WithElementType< // the type C<stripped return type of F> -> typename ContainerType<C>::template ResultOfTransform<F>::type
typename RemoveCvAndReference< // the return type of F stripped
decltype(declval<F>()(declval<typename ContainerType<C>::ElementType>())) // the return type of F
>::type
>::type
{ {
return TransformImpl< return TransformImpl<
typename ContainerType<C>::template WithElementType< // the type C<stripped return type> typename ContainerType<C>::template ResultOfTransform<F>::type,
typename RemoveCvAndReference< // the return type stripped
decltype(declval<F>()(declval<typename ContainerType<C>::ElementType>())) // the return type of F
>::type
>::type,
C C
>::call(container, function); >::call(container, function);
} }
@@ -295,12 +284,10 @@ template<typename C,
typename S> typename S>
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
auto transform(const C &container, R (S::*p)() const) auto transform(const C &container, R (S::*p)() const)
->typename ContainerType<C>::template WithElementType<typename RemoveCvAndReference<R>::type>::type ->typename ContainerType<C>::template ResultOfTransformPMF<R>::type
{ {
return TransformImpl< return TransformImpl<
typename ContainerType<C>::template WithElementType< // the type C<stripped R> typename ContainerType<C>::template ResultOfTransformPMF<R>::type,
typename RemoveCvAndReference<R>::type // stripped R
>::type,
C C
>::call(container, p); >::call(container, p);
} }
@@ -311,16 +298,10 @@ template<template<typename> class C, // result container type
typename F> // function type typename F> // function type
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
auto transform(const SC &container, F function) auto transform(const SC &container, F function)
-> C< // container C<stripped return type of F> -> typename ContainerType<SC>::template ResultOfTransform<F, C>::type
typename RemoveCvAndReference< // stripped return type of F
decltype(declval<F>()(declval<typename ContainerType<SC>::ElementType>())) // return type of F
>::type>
{ {
return TransformImpl< return TransformImpl<
C< // result container type typename ContainerType<SC>::template ResultOfTransform<F, C>::type,
typename RemoveCvAndReference< // stripped
decltype(declval<F>()(declval<typename ContainerType<SC>::ElementType>())) // return type of F
>::type>,
SC SC
>::call(container, function); >::call(container, function);
} }
@@ -333,10 +314,10 @@ template<template<typename> class C, // result container type
typename S> typename S>
Q_REQUIRED_RESULT Q_REQUIRED_RESULT
auto transform(const SC &container, R (S::*p)() const) auto transform(const SC &container, R (S::*p)() const)
-> C<typename RemoveCvAndReference<R>::type> -> C<decay_t<R>>
{ {
return TransformImpl< return TransformImpl<
C<typename RemoveCvAndReference<R>::type>, C<decay_t<R>>,
SC SC
>::call(container, p); >::call(container, p);
} }