Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created January 17, 2014 17:00
Show Gist options
  • Save vittorioromeo/8477066 to your computer and use it in GitHub Desktop.
Save vittorioromeo/8477066 to your computer and use it in GitHub Desktop.
MPL tests
#include <SSVUtils/SSVUtils.hpp>
namespace ssvu
{
namespace MPL
{
template<typename...> struct List;
namespace Internal
{
struct NullType { };
}
using Null = typename Internal::NullType;
template<bool TCond> using BoolResult = Conditional<TCond, std::true_type, std::false_type>;
template<int TN1, int TN2> inline constexpr int getMin() noexcept { return TN1 < TN2 ? TN1 : TN2; }
template<int TN1, int TN2> inline constexpr int getMax() noexcept { return TN1 > TN2 ? TN1 : TN2; }
namespace Internal
{
// VA Args Head
template<typename... TArgs> struct VAHeadHelper;
template<typename T, typename... TArgs> struct VAHeadHelper<T, TArgs...> { using Type = T; };
template<> struct VAHeadHelper<> { using Type = Null; };
template<typename... TArgs> using VAHead = typename Internal::VAHeadHelper<TArgs...>::Type;
// VA Args Tail
template<typename... TArgs> struct VATailHelper;
template<typename T, typename... TArgs> struct VATailHelper<T, TArgs...> { using Type = typename VATailHelper<TArgs...>::Type; };
template<typename T> struct VATailHelper<T> { using Type = T; };
template<> struct VATailHelper<> { using Type = Null; };
template<typename... TArgs> using VATail = typename Internal::VATailHelper<TArgs...>::Type;
// List::PopFront
template<typename> struct PopFrontHelper;
template<typename TL, typename... TLAs> struct PopFrontHelper<List<TL, TLAs...>> { using Type = List<TLAs...>; };
template<> struct PopFrontHelper<List<>> { using Type = List<>; };
// List::PopBack
template<typename, typename> struct RemoveLastHelper;
template<typename TLA1, typename TLA2, typename... TLAs1, typename... TLAs2> struct RemoveLastHelper<List<TLA1, TLA2, TLAs1...>, List<TLAs2...>>
{
using List1 = List<TLA1, TLA2, TLAs1...>;
using List2 = List<TLAs2...>;
using List1WithPop = typename PopFrontHelper<List1>::Type;
using List2WithPush = typename List2::template PushBack<typename List1::Head>;
using Type = typename RemoveLastHelper<List1WithPop, List2WithPush>::Type;
};
template<typename TL1, typename... TLAs2> struct RemoveLastHelper<List<TL1>, List<TLAs2...>> { using Type = List<TLAs2...>; };
template<typename> struct PopBackHelper;
template<typename... TLAs> struct PopBackHelper<List<TLAs...>> { using Type = typename RemoveLastHelper<List<TLAs...>, List<>>::Type; };
template<> struct PopBackHelper<List<>> { using Type = List<>; };
// List::Elem
template<std::size_t, std::size_t, typename, typename> struct GetElemHelper;
template<std::size_t TS, std::size_t TSC, typename TL1> struct GetElemHelperDispatch
{
using Type = typename GetElemHelper<TS, TSC, TL1, BoolResult<TS == TSC>>::Type;
};
template<std::size_t TS, std::size_t TSC, typename... TLAs1> struct GetElemHelper<TS, TSC, List<TLAs1...>, std::false_type>
{
using L1 = List<TLAs1...>;
using L1WithPop = typename PopFrontHelper<L1>::Type;
using Type = typename GetElemHelperDispatch<TS, TSC + 1, L1WithPop>::Type;
};
template<std::size_t TS, std::size_t TSC, typename... TLAs1> struct GetElemHelper<TS, TSC, List<TLAs1...>, std::true_type>
{
using Type = typename List<TLAs1...>::Head;
};
template<std::size_t, typename> struct ElemHelper;
template<std::size_t TS, typename... TLAs> struct ElemHelper<TS, List<TLAs...>> { using Type = typename GetElemHelperDispatch<TS, 0, List<TLAs...>>::Type; };
// List::SubList
template<std::size_t, std::size_t, std::size_t, typename, typename, typename> struct SubListImpl;
template<std::size_t, std::size_t, std::size_t, typename, typename> struct SubListDispatch;
template<std::size_t TS1, std::size_t TS2, std::size_t TSC, typename... TLA1s, typename... TLA2s> struct SubListImpl<TS1, TS2, TSC, List<TLA1s...>, List<TLA2s...>, std::false_type>
{
using Type = typename SubListDispatch<TS1, TS2, TSC + 1, List<TLA1s...>, typename List<TLA2s...>::template PushBack<typename List<TLA1s...>::template Elem<TSC>>>::Type;
};
template<std::size_t TS1, std::size_t TS2, std::size_t TSC, typename... TLA1s, typename... TLA2s> struct SubListImpl<TS1, TS2, TSC, List<TLA1s...>, List<TLA2s...>, std::true_type>
{
using Type = List<TLA2s...>;
};
template<std::size_t TS1, std::size_t TS2, std::size_t TSC, typename TL1, typename TL2> struct SubListDispatch
{
using Type = typename SubListImpl<TS1, TS2, TSC, TL1, TL2, BoolResult<TSC == TS2 || TSC >= TL1::getSize()>>::Type;
};
template<std::size_t, std::size_t, std::size_t, typename> struct SubListHelper;
template<std::size_t TS1, std::size_t TS2, std::size_t TSC, typename... TLAs> struct SubListHelper<TS1, TS2, TSC, List<TLAs...>>
{
using Type = typename SubListDispatch<TS1, TS2, TSC, List<TLAs...>, List<>>::Type;
};
}
template<typename... TArgs> struct List
{
using Head = Internal::VAHead<TArgs...>;
using Tail = Internal::VATail<TArgs...>;
inline static constexpr std::size_t getSize() noexcept { return sizeof...(TArgs); }
template<std::size_t TS> using Elem = typename Internal::ElemHelper<TS, List<TArgs...>>::Type;
template<std::size_t TS> using ElemReverse = Elem<getSize() - 1 - TS>;
template<typename T> using PushBack = List<TArgs..., T>;
template<typename T> using PushFront = List<T, TArgs...>;
using PopBack = typename Internal::PopBackHelper<List<TArgs...>>::Type;
using PopFront = typename Internal::PopFrontHelper<List<TArgs...>>::Type;
template<std::size_t TS1, std::size_t TS2> using SubList = typename Internal::SubListHelper<TS1, TS2, TS1, List<TArgs...>>::Type;
using Clear = List<>;
// TODO: insert
};
namespace Internal
{
namespace Tests
{
static_assert(getMin<15, 10>() == 10, "");
static_assert(getMin<-15, 10>() == -15, "");
static_assert(getMax<15, 10>() == 15, "");
static_assert(getMax<-15, 10>() == 10, "");
static_assert(isSame<Internal::VAHead<int, float, char>, int>(), "");
static_assert(isSame<Internal::VATail<int, float, char>, char>(), "");
static_assert(isSame<List<int, float, char>::Head, int>(), "");
static_assert(isSame<List<int, float, char>::Tail, char>(), "");
static_assert(isSame<List<>::Head, Null>(), "");
static_assert(isSame<List<>::Tail, Null>(), "");
static_assert(isSame<List<int, float, char>::Elem<0>, int>(), "");
static_assert(isSame<List<int, float, char>::Elem<1>, float>(), "");
static_assert(isSame<List<int, float, char>::Elem<2>, char>(), "");
static_assert(isSame<List<int, float, char>::ElemReverse<0>, char>(), "");
static_assert(isSame<List<int, float, char>::ElemReverse<1>, float>(), "");
static_assert(isSame<List<int, float, char>::ElemReverse<2>, int>(), "");
static_assert(isSame<List<>::PushBack<int>, List<int>>(), "");
static_assert(isSame<List<int>::PushBack<float>, List<int, float>>(), "");
static_assert(isSame<List<int, float>::PushBack<char>, List<int, float, char>>(), "");
static_assert(isSame<List<>::PushFront<int>, List<int>>(), "");
static_assert(isSame<List<int>::PushFront<float>, List<float, int>>(), "");
static_assert(isSame<List<float, int>::PushFront<char>, List<char, float, int>>(), "");
static_assert(isSame<List<int, float, char>::PopBack, List<int, float>>(), "");
static_assert(isSame<List<int, float>::PopBack, List<int>>(), "");
static_assert(isSame<List<int>::PopBack, List<>>(), "");
static_assert(isSame<List<>::PopBack, List<>>(), "");
static_assert(isSame<List<int, float, char>::PopFront, List<float, char>>(), "");
static_assert(isSame<List<float, char>::PopFront, List<char>>(), "");
static_assert(isSame<List<char>::PopFront, List<>>(), "");
static_assert(isSame<List<>::PopFront, List<>>(), "");
// 0 1 2 3 4
static_assert(isSame<List<int, float, char, float, int>::SubList<0, 0>, List<>>(), "");
static_assert(isSame<List<int, float, char, float, int>::SubList<0, 1>, List<int>>(), "");
static_assert(isSame<List<int, float, char, float, int>::SubList<0, 3>, List<int, float, char>>(), "");
static_assert(isSame<List<int, float, char, float, int>::SubList<2, 4>, List<char, float>>(), "");
static_assert(isSame<List<int, float, char, float, int>::SubList<0, 999>, List<int, float, char, float, int>>(), "");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment