Created
January 17, 2014 17:00
-
-
Save vittorioromeo/8477066 to your computer and use it in GitHub Desktop.
MPL tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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