alsk/inc/tmp/packalgo.h
2021-05-10 18:14:13 +02:00

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