168 lines
3.6 KiB
C
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
|