alsk/inc/tmp/pack.h

168 lines
3.6 KiB
C++

#ifndef TMP_PACK_H
#define TMP_PACK_H
#include "utility.h"
namespace tmp {
/**
* Pack
*/
template<typename... Ts> struct Pack {
static constexpr Size size = sizeof...(Ts);
};
/**
* PackHead
*/
template<typename> struct PackHeadImpl;
template<typename T, typename... Ts>
struct PackHeadImpl<Pack<T, Ts...>> {
using type = T;
};
template<typename T>
using PackHead = typename PackHeadImpl<T>::type;
/**
* PackTrail
*/
template<typename> struct PackTrailImpl;
template<typename T, typename... Ts>
struct PackTrailImpl<Pack<T, Ts...>> {
using type = Pack<Ts...>;
};
template<typename T>
using PackTrail = typename PackTrailImpl<T>::type;
/**
* PackGet
*/
template<typename, Size> struct PackGetImpl;
template<typename T, typename... Ts, Size I>
struct PackGetImpl<Pack<T, Ts...>, I> {
using type = typename PackGetImpl<Pack<Ts...>, I-1>::type;
};
template<typename T, typename... Ts>
struct PackGetImpl<Pack<T, Ts...>, 0> {
using type = T;
};
template<typename T, Size I>
using PackGet = typename PackGetImpl<T, I>::type;
/**
* PackPushFront
*/
template<typename, typename> struct PackPushFrontImpl;
template<typename... Ts, typename T>
struct PackPushFrontImpl<Pack<Ts...>, T> {
using type = Pack<T, Ts...>;
};
template<typename P, typename T>
using PackPushFront = typename PackPushFrontImpl<P, T>::type;
/**
* PackPushBack
*/
template<typename, typename> struct PackPushBackImpl;
template<typename... Ts, typename T>
struct PackPushBackImpl<Pack<Ts...>, T> {
using type = Pack<Ts..., T>;
};
template<typename P, typename T>
using PackPushBack = typename PackPushBackImpl<P, T>::type;
/**
* PackCat
*/
template<typename...> struct PackCatImpl;
template<typename... Ts, typename... Us, typename... Packs>
struct PackCatImpl<Pack<Ts...>, Pack<Us...>, Packs...> {
using type = typename PackCatImpl<Pack<Ts..., Us...>, Packs...>::type;
};
template<typename... Ts>
struct PackCatImpl<Pack<Ts...>> {
using type = Pack<Ts...>;
};
template<>
struct PackCatImpl<> {
using type = Pack<>;
};
template<typename... Packs>
using PackCat = typename PackCatImpl<Packs...>::type;
/**
* PackReverse
*/
template<typename> struct PackReverseImpl;
template<typename T, typename... Ts>
struct PackReverseImpl<Pack<T, Ts...>> {
using type = PackPushBack<typename PackReverseImpl<Pack<Ts...>>::type, T>;
};
template<>
struct PackReverseImpl<Pack<>> {
using type = Pack<>;
};
template<typename P>
using PackReverse = typename PackReverseImpl<P>::type;
/**
* PackReplace
*/
template<typename, typename, typename> struct PackReplaceImpl;
template<typename Before, typename After, typename Current, typename... Ts>
struct PackReplaceImpl<Pack<Current, Ts...>, Before, After> {
using type = PackCat<Pack<Current>, typename PackReplaceImpl<Pack<Ts...>, Before, After>::type>;
};
template<typename Before, typename After, typename... Ts>
struct PackReplaceImpl<Pack<Before, Ts...>, Before, After> {
using type = PackCat<Pack<After>, typename PackReplaceImpl<Pack<Ts...>, Before, After>::type>;
};
template<typename Before, typename After>
struct PackReplaceImpl<Pack<>, Before, After> {
using type = Pack<>;
};
template<typename P, typename Before, typename After>
using PackReplace = typename PackReplaceImpl<P, Before, After>::type;
/**
* Repack
*/
template<template<typename...> class, typename> struct RepackImpl;
template<template<typename...> class Out, template<typename...> class In, typename... Ts>
struct RepackImpl<Out, In<Ts...>> {
using type = Out<Ts...>;
};
template<template<typename...> class Out, typename In>
using Repack = typename RepackImpl<Out, In>::type;
/**
* AsPack
*/
template<typename T>
using AsPack = Repack<Pack, T>;
}
#endif