104 lines
2.7 KiB
C
104 lines
2.7 KiB
C
|
#ifndef TMP_PACKALGO_H
|
||
|
#define TMP_PACKALGO_H
|
||
|
|
||
|
#include "pack.h"
|
||
|
#include "traits.h"
|
||
|
|
||
|
namespace tmp {
|
||
|
|
||
|
/**
|
||
|
* Transform
|
||
|
*/
|
||
|
template<typename, template<typename...> class> struct TransformImpl;
|
||
|
template<typename T, typename... Ts, template<typename...> class F>
|
||
|
struct TransformImpl<Pack<T, Ts...>, F> {
|
||
|
using type = PackPushFront<typename TransformImpl<Pack<Ts...>, F>::type, F<T>>;
|
||
|
};
|
||
|
|
||
|
template<template<typename...> class F>
|
||
|
struct TransformImpl<Pack<>, F> {
|
||
|
using type = Pack<>;
|
||
|
};
|
||
|
|
||
|
template<typename P, template<typename...> class F>
|
||
|
using Transform = typename TransformImpl<P, F>::type;
|
||
|
|
||
|
/**
|
||
|
* Accumulate
|
||
|
*/
|
||
|
template<typename, template<typename, typename> class, typename> struct AccumulateImpl;
|
||
|
template<typename T, typename... Ts, template<typename, typename> class F, typename A>
|
||
|
struct AccumulateImpl<Pack<T, Ts...>, F, A> {
|
||
|
using type = typename AccumulateImpl<Pack<Ts...>, F, F<A, T>>::type;
|
||
|
};
|
||
|
|
||
|
template<template<typename, typename> class F, typename A>
|
||
|
struct AccumulateImpl<Pack<>, F, A> {
|
||
|
using type = A;
|
||
|
};
|
||
|
|
||
|
template<typename P, template<typename, typename> class F, typename A>
|
||
|
using Accumulate = typename AccumulateImpl<P, F, A>::type;
|
||
|
|
||
|
/**
|
||
|
* Filter
|
||
|
*/
|
||
|
template<typename, template<typename> class> struct FilterImpl;
|
||
|
template<typename T, typename... Ts, template<typename> class F>
|
||
|
struct FilterImpl<Pack<T, Ts...>, F> {
|
||
|
using next = typename FilterImpl<Pack<Ts...>, F>::type;
|
||
|
using type = std::conditional_t<F<T>::value, PackPushFront<next, T>, next>;
|
||
|
};
|
||
|
|
||
|
template<template<typename> class F>
|
||
|
struct FilterImpl<Pack<>, F> {
|
||
|
using type = Pack<>;
|
||
|
};
|
||
|
|
||
|
template<typename P, template<typename> class F>
|
||
|
using Filter = typename FilterImpl<P, F>::type;
|
||
|
|
||
|
/**
|
||
|
* Cut
|
||
|
*/
|
||
|
template<typename, typename, template<typename> class> struct CutImpl;
|
||
|
template<typename R, typename... Rs, typename... Ls, template<typename> class F>
|
||
|
struct CutImpl<Pack<Ls...>, Pack<R, Rs...>, F> {
|
||
|
using next = typename CutImpl<Pack<Ls..., R>, Pack<Rs...>, F>::type;
|
||
|
using type = std::conditional_t<F<R>::value, next, Pack<Pack<Ls...>, Pack<R, Rs...>>>;
|
||
|
};
|
||
|
|
||
|
template<typename... Ls, template<typename> class F>
|
||
|
struct CutImpl<Pack<Ls...>, Pack<>, F> {
|
||
|
using type = Pack<Pack<Ls...>, Pack<>>;
|
||
|
};
|
||
|
|
||
|
template<template<typename> class F>
|
||
|
struct CutImpl<Pack<>, Pack<>, F> {
|
||
|
using type = Pack<Pack<>, Pack<>>;
|
||
|
};
|
||
|
|
||
|
template<typename P, template<typename> class F>
|
||
|
using Cut = typename CutImpl<Pack<>, P, F>::type;
|
||
|
|
||
|
/**
|
||
|
* Reverse
|
||
|
*/
|
||
|
template<typename> struct ReverseImpl;
|
||
|
template<typename T, typename... Ts>
|
||
|
struct ReverseImpl<Pack<T, Ts...>> {
|
||
|
using type = PackPushBack<typename ReverseImpl<Pack<Ts...>>::type, T>;
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct ReverseImpl<Pack<>> {
|
||
|
using type = Pack<>;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
using Reverse = typename ReverseImpl<T>::type;
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|