Core/TypeList: Add Apply, Empty and Size operations
This commit is contained in:
parent
1a1e16e9df
commit
7cd772a254
|
|
@ -18,6 +18,9 @@ namespace Nz
|
||||||
template<typename, typename>
|
template<typename, typename>
|
||||||
struct ListAppend;
|
struct ListAppend;
|
||||||
|
|
||||||
|
template<typename, template<typename> typename>
|
||||||
|
struct ListApply;
|
||||||
|
|
||||||
template<typename, std::size_t>
|
template<typename, std::size_t>
|
||||||
struct ListAt;
|
struct ListAt;
|
||||||
|
|
||||||
|
|
@ -33,6 +36,9 @@ namespace Nz
|
||||||
template<typename, typename>
|
template<typename, typename>
|
||||||
struct ListPrepend;
|
struct ListPrepend;
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
struct ListSize;
|
||||||
|
|
||||||
template<typename, typename>
|
template<typename, typename>
|
||||||
struct ListUnique;
|
struct ListUnique;
|
||||||
}
|
}
|
||||||
|
|
@ -40,12 +46,18 @@ namespace Nz
|
||||||
template<typename List, typename NewType>
|
template<typename List, typename NewType>
|
||||||
using TypeListAppend = typename Detail::ListAppend<List, NewType>::Result;
|
using TypeListAppend = typename Detail::ListAppend<List, NewType>::Result;
|
||||||
|
|
||||||
|
template<typename List, template<typename> typename Functor, typename... Args>
|
||||||
|
void TypeListApply(Args&&... args);
|
||||||
|
|
||||||
template<typename List, std::size_t Index>
|
template<typename List, std::size_t Index>
|
||||||
using TypeListAt = typename Detail::ListAt<List, Index>::Type;
|
using TypeListAt = typename Detail::ListAt<List, Index>::Type;
|
||||||
|
|
||||||
template<typename FirstList, typename SecondList>
|
template<typename FirstList, typename SecondList>
|
||||||
using TypeListConcat = typename Detail::ListConcat<FirstList, SecondList>::Result;
|
using TypeListConcat = typename Detail::ListConcat<FirstList, SecondList>::Result;
|
||||||
|
|
||||||
|
template<typename List>
|
||||||
|
constexpr bool TypeListEmpty = Detail::ListSize<List>::Size == 0;
|
||||||
|
|
||||||
template<typename List, typename Type>
|
template<typename List, typename Type>
|
||||||
constexpr bool TypeListFind = Detail::ListFind<List, Type>::Find();
|
constexpr bool TypeListFind = Detail::ListFind<List, Type>::Find();
|
||||||
|
|
||||||
|
|
@ -55,6 +67,9 @@ namespace Nz
|
||||||
template<typename List, typename NewType>
|
template<typename List, typename NewType>
|
||||||
using TypeListPrepend = typename Detail::ListPrepend<List, NewType>::Result;
|
using TypeListPrepend = typename Detail::ListPrepend<List, NewType>::Result;
|
||||||
|
|
||||||
|
template<typename List>
|
||||||
|
constexpr std::size_t TypeListSize = Detail::ListSize<List>::Size;
|
||||||
|
|
||||||
template<typename List>
|
template<typename List>
|
||||||
using TypeListUnique = typename Detail::ListUnique<TypeList<>, List>::Result;
|
using TypeListUnique = typename Detail::ListUnique<TypeList<>, List>::Result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,109 +4,139 @@
|
||||||
|
|
||||||
#include <Nazara/Core/TypeList.hpp>
|
#include <Nazara/Core/TypeList.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz::Detail
|
namespace Nz
|
||||||
{
|
{
|
||||||
template<typename NewType, typename... ListTypes>
|
namespace Detail
|
||||||
struct ListAppend<TypeList<ListTypes...>, NewType>
|
|
||||||
{
|
{
|
||||||
using Result = TypeList<ListTypes..., NewType>;
|
template<typename NewType, typename... ListTypes>
|
||||||
};
|
struct ListAppend<TypeList<ListTypes...>, NewType>
|
||||||
|
|
||||||
|
|
||||||
template<typename T, typename... ListTypes>
|
|
||||||
struct ListAt<TypeList<T, ListTypes...>, 0>
|
|
||||||
{
|
|
||||||
using Type = T;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t Index, typename T, typename... ListTypes>
|
|
||||||
struct ListAt<TypeList<T, ListTypes...>, Index>
|
|
||||||
{
|
|
||||||
static_assert(Index <= sizeof...(ListTypes), "Index out of range");
|
|
||||||
|
|
||||||
using Type = typename ListAt<TypeList<ListTypes...>, Index - 1>::Type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename... First>
|
|
||||||
struct ListConcat<TypeList<First...>, TypeList<>>
|
|
||||||
{
|
|
||||||
using Result = TypeList<First...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Second>
|
|
||||||
struct ListConcat<TypeList<>, TypeList<Second...>>
|
|
||||||
{
|
|
||||||
using Result = TypeList<Second...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... First, typename T>
|
|
||||||
struct ListConcat<TypeList<First...>, TypeList<T>>
|
|
||||||
{
|
|
||||||
using Result = TypeList<First..., T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... First, typename T1, typename T2, typename... Second>
|
|
||||||
struct ListConcat<TypeList<First...>, TypeList<T1, T2, Second...>>
|
|
||||||
{
|
|
||||||
using Result = typename ListConcat<TypeList<First..., T1>, TypeList<T2, Second...>>::Result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ListFindHelper
|
|
||||||
{
|
|
||||||
template<typename ToFind, typename Type, typename... Rest> static constexpr bool Find()
|
|
||||||
{
|
{
|
||||||
if constexpr (std::is_same_v<ToFind, Type>)
|
using Result = TypeList<ListTypes..., NewType>;
|
||||||
return true;
|
};
|
||||||
else
|
|
||||||
return Find<ToFind, Rest...>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ToFind> static constexpr bool Find()
|
|
||||||
|
template<template<typename> typename Functor, typename T, typename... ListTypes>
|
||||||
|
struct ListApply<TypeList<T, ListTypes...>, Functor>
|
||||||
{
|
{
|
||||||
return false;
|
template<typename... Args>
|
||||||
}
|
static void Apply(Args&&... args)
|
||||||
};
|
{
|
||||||
|
Functor<T>()(std::forward<Args>(args)...);
|
||||||
|
if constexpr (sizeof...(ListTypes) > 0)
|
||||||
|
ListApply<TypeList<ListTypes...>, Functor>::Apply(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename TypeToFind, typename... ListTypes>
|
template<typename T, typename... ListTypes>
|
||||||
struct ListFind<TypeList<ListTypes...>, TypeToFind>
|
struct ListAt<TypeList<T, ListTypes...>, 0>
|
||||||
{
|
|
||||||
static constexpr bool Find()
|
|
||||||
{
|
{
|
||||||
return ListFindHelper::Find<TypeToFind, ListTypes...>();
|
using Type = T;
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
template<std::size_t Index, typename T, typename... ListTypes>
|
||||||
|
struct ListAt<TypeList<T, ListTypes...>, Index>
|
||||||
|
{
|
||||||
|
static_assert(Index <= sizeof...(ListTypes), "Index out of range");
|
||||||
|
|
||||||
|
using Type = typename ListAt<TypeList<ListTypes...>, Index - 1>::Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<template<typename...> typename Class, typename... ListTypes>
|
template<typename... First>
|
||||||
struct ListInstantiate<TypeList<ListTypes...>, Class>
|
struct ListConcat<TypeList<First...>, TypeList<>>
|
||||||
|
{
|
||||||
|
using Result = TypeList<First...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Second>
|
||||||
|
struct ListConcat<TypeList<>, TypeList<Second...>>
|
||||||
|
{
|
||||||
|
using Result = TypeList<Second...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... First, typename T>
|
||||||
|
struct ListConcat<TypeList<First...>, TypeList<T>>
|
||||||
|
{
|
||||||
|
using Result = TypeList<First..., T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... First, typename T1, typename T2, typename... Second>
|
||||||
|
struct ListConcat<TypeList<First...>, TypeList<T1, T2, Second...>>
|
||||||
|
{
|
||||||
|
using Result = typename ListConcat<TypeList<First..., T1>, TypeList<T2, Second...>>::Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ListFindHelper
|
||||||
|
{
|
||||||
|
template<typename ToFind, typename Type, typename... Rest> static constexpr bool Find()
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<ToFind, Type>)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return Find<ToFind, Rest...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ToFind> static constexpr bool Find()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TypeToFind, typename... ListTypes>
|
||||||
|
struct ListFind<TypeList<ListTypes...>, TypeToFind>
|
||||||
|
{
|
||||||
|
static constexpr bool Find()
|
||||||
|
{
|
||||||
|
return ListFindHelper::Find<TypeToFind, ListTypes...>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<template<typename...> typename Class, typename... ListTypes>
|
||||||
|
struct ListInstantiate<TypeList<ListTypes...>, Class>
|
||||||
|
{
|
||||||
|
using Result = Class<ListTypes...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename NewType, typename... ListTypes>
|
||||||
|
struct ListPrepend<TypeList<ListTypes...>, NewType>
|
||||||
|
{
|
||||||
|
using Result = TypeList<NewType, ListTypes...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... ListTypes>
|
||||||
|
struct ListSize<TypeList<ListTypes...>>
|
||||||
|
{
|
||||||
|
static constexpr std::size_t Size = sizeof...(ListTypes);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... Types, typename T1>
|
||||||
|
struct ListUnique<TypeList<Types...>, TypeList<T1>>
|
||||||
|
{
|
||||||
|
static constexpr bool IsTypePresent = ListFind<TypeList<Types...>, T1>::Find();
|
||||||
|
using Result = std::conditional_t<!IsTypePresent, TypeList<Types..., T1>, TypeList<Types...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Types, typename T1, typename T2, typename... Rest>
|
||||||
|
struct ListUnique<TypeList<Types...>, TypeList<T1, T2, Rest...>>
|
||||||
|
{
|
||||||
|
using Result = typename ListUnique<typename ListUnique<TypeList<Types...>, TypeList<T1>>::Result, TypeList<T2, Rest...>>::Result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename List, template<typename> typename Functor, typename... Args>
|
||||||
|
void TypeListApply(Args&&... args)
|
||||||
{
|
{
|
||||||
using Result = Class<ListTypes...>;
|
if constexpr (!TypeListEmpty<List>)
|
||||||
};
|
Detail::ListApply<List, Functor>::Apply(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename NewType, typename... ListTypes>
|
|
||||||
struct ListPrepend<TypeList<ListTypes...>, NewType>
|
|
||||||
{
|
|
||||||
using Result = TypeList<NewType, ListTypes...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename... Types, typename T1>
|
|
||||||
struct ListUnique<TypeList<Types...>, TypeList<T1>>
|
|
||||||
{
|
|
||||||
static constexpr bool IsTypePresent = ListFind<TypeList<Types...>, T1>::Find();
|
|
||||||
using Result = std::conditional_t<!IsTypePresent, TypeList<Types..., T1>, TypeList<Types...>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Types, typename T1, typename T2, typename... Rest>
|
|
||||||
struct ListUnique<TypeList<Types...>, TypeList<T1, T2, Rest...>>
|
|
||||||
{
|
|
||||||
using Result = typename ListUnique<typename ListUnique<TypeList<Types...>, TypeList<T1>>::Result, TypeList<T2, Rest...>>::Result;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Core/DebugOff.hpp>
|
#include <Nazara/Core/DebugOff.hpp>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue