281 lines
7.3 KiB
C
281 lines
7.3 KiB
C
|
#pragma once
|
||
|
|
||
|
#include "CoreTypes.h"
|
||
|
#include "Templates/Utility.h"
|
||
|
#include "Templates/Container.h"
|
||
|
#include "TypeTraits/TypeTraits.h"
|
||
|
|
||
|
NAMESPACE_REDCRAFT_BEGIN
|
||
|
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||
|
NAMESPACE_MODULE_BEGIN(Utility)
|
||
|
|
||
|
template <typename T, T... Ints>
|
||
|
struct TIntegerSequence
|
||
|
{
|
||
|
using ValueType = T;
|
||
|
static constexpr size_t Num() { return sizeof...(Ints); }
|
||
|
static constexpr const T* GetData() { return NAMESPACE_REDCRAFT::GetData({ Ints... }); }
|
||
|
};
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
|
||
|
template <unsigned N, typename T>
|
||
|
struct TMakeIntegerSequenceImpl
|
||
|
{
|
||
|
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
|
||
|
};
|
||
|
|
||
|
#elif __has_builtin(__make_integer_seq)
|
||
|
|
||
|
template <unsigned N, typename T>
|
||
|
struct TMakeIntegerSequenceImpl
|
||
|
{
|
||
|
using Type = typename __make_integer_seq<TIntegerSequence, T, N>;
|
||
|
};
|
||
|
|
||
|
#else
|
||
|
|
||
|
template <unsigned N, typename T, T... Ints>
|
||
|
struct TMakeIntegerSequenceImpl
|
||
|
{
|
||
|
using Type = typename TMakeIntegerSequenceImpl<N - 1, T, T(N - 1), Ints...>::Type;
|
||
|
};
|
||
|
|
||
|
template <typename T, T... Ints>
|
||
|
struct TMakeIntegerSequenceImpl<0, T, Ints...>
|
||
|
{
|
||
|
using Type = TIntegerSequence<T, Ints...>;
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <size_t... Ints>
|
||
|
using TIndexSequence = TIntegerSequence<size_t, Ints...>;
|
||
|
|
||
|
template <typename T, T N>
|
||
|
using TMakeIntegerSequence = typename NAMESPACE_PRIVATE::TMakeIntegerSequenceImpl<N, T>::Type;
|
||
|
|
||
|
template <size_t N>
|
||
|
using TMakeIndexSequence = TMakeIntegerSequence<size_t, N>;
|
||
|
|
||
|
template <typename... Ts>
|
||
|
using TIndexSequenceFor = TMakeIndexSequence<sizeof...(Ts)>;
|
||
|
|
||
|
template <typename... Ts>
|
||
|
struct TTypeSequence { };
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename T > struct TIsTIntegerSequence : FFalse { };
|
||
|
template <typename T, T... Ints> struct TIsTIntegerSequence<TIntegerSequence<T, Ints...>> : FTrue { };
|
||
|
|
||
|
template <typename T > struct TIsTIndexSequence : FFalse { };
|
||
|
template <size_t... Ints> struct TIsTIndexSequence<TIndexSequence<Ints...>> : FTrue { };
|
||
|
|
||
|
template <typename T > struct TIsTTypeSequence : FFalse { };
|
||
|
template <typename... Ts> struct TIsTTypeSequence<TTypeSequence<Ts...>> : FTrue { };
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
// Unlike other places such as CTTuple, cv-qualifiers are not ignored here
|
||
|
// This is done to simplify the logic and make it easier to use it
|
||
|
|
||
|
template <typename T>
|
||
|
concept CTIntegerSequence = NAMESPACE_PRIVATE::TIsTIntegerSequence<T>::Value;
|
||
|
|
||
|
template <typename T>
|
||
|
concept CTIndexSequence = NAMESPACE_PRIVATE::TIsTIndexSequence<T>::Value;
|
||
|
|
||
|
template <typename T>
|
||
|
concept CTTypeSequence = NAMESPACE_PRIVATE::TIsTTypeSequence<T>::Value;
|
||
|
|
||
|
NAMESPACE_BEGIN(Meta)
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TFrontImpl;
|
||
|
|
||
|
template <typename T, typename... Ts>
|
||
|
struct TFrontImpl<TTypeSequence<T, Ts...>>
|
||
|
{
|
||
|
using Type = T;
|
||
|
};
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TPopImpl;
|
||
|
|
||
|
template <typename T, typename... Ts>
|
||
|
struct TPopImpl<TTypeSequence<T, Ts...>>
|
||
|
{
|
||
|
using Type = TTypeSequence<Ts...>;
|
||
|
};
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
struct TPushImpl;
|
||
|
|
||
|
template <typename T, typename... Ts>
|
||
|
struct TPushImpl<T, TTypeSequence<Ts...>>
|
||
|
{
|
||
|
using Type = TTypeSequence<T, Ts...>;
|
||
|
};
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <CTTypeSequence TSequence>
|
||
|
using TFront = typename NAMESPACE_PRIVATE::TFrontImpl<TSequence>::Type;
|
||
|
|
||
|
template <CTTypeSequence TSequence>
|
||
|
using TPop = typename NAMESPACE_PRIVATE::TPopImpl<TSequence>::Type;
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
using TPush = typename NAMESPACE_PRIVATE::TPushImpl<T, TSequence>::Type;
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
struct TTypeCountImpl
|
||
|
{
|
||
|
static constexpr size_t Value = (CSameAs<T, TFront<TSequence>> ? 1 : 0) + TTypeCountImpl<T, TPop<TSequence>>::Value;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
struct TTypeCountImpl<T, TTypeSequence<>>
|
||
|
{
|
||
|
static constexpr size_t Value = 0;
|
||
|
};
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <typename T, CTTypeSequence TSequence>
|
||
|
inline constexpr size_t TTypeCount = NAMESPACE_PRIVATE::TTypeCountImpl<T, TSequence>::Value;
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
concept CExistentType = CTTypeSequence<TSequence> && TTypeCount<T, TSequence> > 0;
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
concept CDuplicateType = CTTypeSequence<TSequence> && TTypeCount<T, TSequence> > 1;
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TSizeImpl;
|
||
|
|
||
|
template <typename... Ts>
|
||
|
struct TSizeImpl<TTypeSequence<Ts...>>
|
||
|
{
|
||
|
static constexpr size_t Value = sizeof...(Ts);
|
||
|
};
|
||
|
|
||
|
template <size_t I, typename T, typename TSequence>
|
||
|
struct TIndexImpl
|
||
|
{
|
||
|
static constexpr size_t Value = CSameAs<T, TFront<TSequence>> ? I : TIndexImpl<I + 1, T, TPop<TSequence>>::Value;
|
||
|
};
|
||
|
|
||
|
template <size_t I, typename T>
|
||
|
struct TIndexImpl<I, T, TTypeSequence<>>
|
||
|
{
|
||
|
static constexpr size_t Value = INDEX_NONE;
|
||
|
};
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
struct TIndexAssert
|
||
|
{
|
||
|
static_assert( Meta::CExistentType< T, TSequence>, "T is non-existent types in type sequence");
|
||
|
static_assert(!Meta::CDuplicateType<T, TSequence>, "T is duplicate type in type sequence" );
|
||
|
static constexpr size_t Value = TIndexImpl<0, T, TSequence>::Value;
|
||
|
};
|
||
|
|
||
|
template <size_t I, typename TSequence>
|
||
|
struct TTypeImpl
|
||
|
{
|
||
|
using Type = typename TTypeImpl<I - 1, TPop<TSequence>>::Type;
|
||
|
};
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TTypeImpl<0, TSequence>
|
||
|
{
|
||
|
using Type = TFront<TSequence>;
|
||
|
};
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TTypeImpl<INDEX_NONE, TSequence>
|
||
|
{
|
||
|
using Type = void;
|
||
|
};
|
||
|
|
||
|
template <size_t I, typename TSequence>
|
||
|
struct TTypeAssert
|
||
|
{
|
||
|
static_assert(I < TSizeImpl<TSequence>::Value, "I is invalid index in type sequence");
|
||
|
static constexpr size_t SafeIndex = I < TSizeImpl<TSequence>::Value ? I : INDEX_NONE;
|
||
|
using Type = TCopyCV<TSequence, typename TTypeImpl<SafeIndex, TSequence>::Type>;
|
||
|
};
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <CTTypeSequence TSequence>
|
||
|
inline constexpr size_t TSize = NAMESPACE_PRIVATE::TSizeImpl<TSequence>::Value;
|
||
|
|
||
|
template <typename T, CTTypeSequence TSequence>
|
||
|
inline constexpr size_t TIndex = NAMESPACE_PRIVATE::TIndexAssert<T, TSequence>::Value;
|
||
|
|
||
|
template <size_t I, CTTypeSequence TSequence>
|
||
|
using TType = typename NAMESPACE_PRIVATE::TTypeAssert<I, TSequence>::Type;
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TUniqueTypeSequenceImpl
|
||
|
{
|
||
|
using FrontType = TFront<TSequence>;
|
||
|
using NextSequence = TPop<TSequence>;
|
||
|
using NextUniqueSequence = typename TUniqueTypeSequenceImpl<NextSequence>::Type;
|
||
|
using Type = TConditional<!CExistentType<FrontType, NextSequence>, TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct TUniqueTypeSequenceImpl<TTypeSequence<>>
|
||
|
{
|
||
|
using Type = TTypeSequence<>;
|
||
|
};
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <CTTypeSequence TSequence>
|
||
|
using TUniqueTypeSequence = typename NAMESPACE_PRIVATE::TUniqueTypeSequenceImpl<TSequence>::Type;
|
||
|
|
||
|
NAMESPACE_PRIVATE_BEGIN
|
||
|
|
||
|
template <typename T>
|
||
|
struct TOverload
|
||
|
{
|
||
|
using F = T(*)(T);
|
||
|
operator F() const { return nullptr; }
|
||
|
};
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TOverloadSetImpl;
|
||
|
|
||
|
template <typename... Ts>
|
||
|
struct TOverloadSetImpl<TTypeSequence<Ts...>> : public TOverload<Ts>... { };
|
||
|
|
||
|
template <typename TSequence>
|
||
|
struct TOverloadSet : public TOverloadSetImpl<TUniqueTypeSequence<TSequence>> { };
|
||
|
|
||
|
NAMESPACE_PRIVATE_END
|
||
|
|
||
|
template <typename T, typename TSequence>
|
||
|
using TOverloadResolution = decltype(DeclVal<NAMESPACE_PRIVATE::TOverloadSet<TSequence>>()(DeclVal<T>()));
|
||
|
|
||
|
NAMESPACE_END(Meta)
|
||
|
|
||
|
NAMESPACE_MODULE_END(Utility)
|
||
|
NAMESPACE_MODULE_END(Redcraft)
|
||
|
NAMESPACE_REDCRAFT_END
|