Skip to content

Reference to Chapter 3. Typelists In Modern C++ Design and implement with c++17

Notifications You must be signed in to change notification settings

andywang0607/TypeList

Repository files navigation

TypeList

Reference to Chapter 3. Typelists In Modern C++ Design and implement with c++17

template <typename... Types>
struct TypeList;

using NullType = TypeList<>;

template <typename TypeList>
struct Length;

template <typename... Types>
struct Length<TypeList<Types...>>
{
    constexpr static int Result = sizeof...(Types);
};

template <typename TypeList, typename NewType>
struct Append;

template <typename... Types, typename NewType>
struct Append<TypeList<Types...>, NewType>
{
    using Result = TypeList<Types..., NewType>;
};

template <typename... Types, typename... NewTypes>
struct Append<TypeList<Types...>, TypeList<NewTypes...>>
{
    using Result = TypeList<Types..., NewTypes...>;
};

template <>
struct Append<NullType, NullType>
{
    using Result = NullType;
};

template <typename TypeList, std::size_t Index>
struct TypeAt;

template <typename Head, typename... Tail>
struct TypeAt<TypeList<Head, Tail...>, 0>
{
    using Result = Head;
};

template <typename Head, typename... Tail, std::size_t Index>
struct TypeAt<TypeList<Head, Tail...>, Index>
{
    using Result = typename TypeAt<TypeList<Tail...>, Index - 1>::Result;
};

template <>
struct TypeAt<NullType, 0>
{
    using Result = NullType;
};

template <typename TypeList, typename TargetType>
struct IndexOf;

template <typename TargetType>
struct IndexOf<NullType, TargetType>
{
    constexpr static int Result = -1;
};

template <typename... Types, typename TargetType>
struct IndexOf<TypeList<TargetType, Types...>, TargetType>
{
    constexpr static int Result = 0;
};

template <typename Head, typename... Tails, typename TargetType>
struct IndexOf<TypeList<Head, Tails...>, TargetType>
{
private:
    constexpr static int Temp = IndexOf<TypeList<Tails...>, TargetType>::Result;

public:
    constexpr static int Result = Temp == -1 ? -1 : Temp + 1;
};

template <typename TypeList, typename TargetType>
struct Erase;

template <typename TargetType>
struct Erase<NullType, TargetType>
{
    using Result = NullType;
};

template <typename Head, typename... Tails>
struct Erase<TypeList<Head, Tails...>, Head>
{
    using Result = TypeList<Tails...>;
};

template <typename Head, typename... Tails, typename TargetType>
struct Erase<TypeList<Head, Tails...>, TargetType>
{
    using Result = typename Append<TypeList<Head>, typename Erase<TypeList<Tails...>, TargetType>::Result>::Result;
};

template <typename TypeList, typename TargetType>
struct EraseAll;

template <typename TargetType>
struct EraseAll<NullType, TargetType>
{
    using Result = NullType;
};

template <typename Head, typename... Tails, typename TargetType>
struct EraseAll<TypeList<Head, Tails...>, TargetType>
{
    using Result = typename Append<TypeList<Head>, typename EraseAll<TypeList<Tails...>, TargetType>::Result>::Result;
};

template <typename... Types, typename TargetType>
struct EraseAll<TypeList<TargetType, Types...>, TargetType>
{
    using Result = typename EraseAll<TypeList<Types...>, TargetType>::Result;
};

template <typename TypeList>
struct EraseDuplicates;

template <>
struct EraseDuplicates<NullType>
{
    using Result = NullType;
};

template <typename Head, typename... Tails>
struct EraseDuplicates<TypeList<Head, Tails...>>
{
private:
    using Temp = typename EraseDuplicates<TypeList<Tails...>>::Result;
    using Temp2 = typename Erase<Temp, Head>::Result;
public:
    using Result = typename Append<TypeList<Head>, Temp2>::Result;
};

template <typename TypeList, typename ToReplace, typename NewType>
struct Replace;

template <typename ToReplace, typename NewType>
struct Replace<NullType, ToReplace, NewType>
{
    using Result = NullType;
};

template <typename... Tails, typename ToReplace, typename NewType>
struct Replace<TypeList<ToReplace, Tails...>, ToReplace, NewType>
{
    using Result = TypeList<NewType, Tails...>;
};

template <typename Head, typename... Tails, typename ToReplace, typename NewType>
struct Replace<TypeList<Head, Tails...>, ToReplace, NewType>
{
    using Result = typename Append<TypeList<Head>, typename Replace<TypeList<Tails...>, ToReplace, NewType>::Result>::Result;
};

template <typename TypeList, typename BaseType>
struct MostDerived;

template <typename BaseType>
struct MostDerived<NullType, BaseType>
{
    using Result = BaseType;
};

template <typename Head, typename... Tails, typename BaseType>
struct MostDerived<TypeList<Head, Tails...>, BaseType>
{
private:
    using Candidate = typename MostDerived<TypeList<Tails...>, BaseType>::Result;
public:
    using Result = typename std::conditional_t<std::is_base_of_v<Head, Candidate>, Candidate, Head>;
};

template <typename TypeList>
struct DerivedToFront;

template <>
struct DerivedToFront<NullType>
{
    using Result = NullType;
};

template <typename Head, typename... Tails>
struct DerivedToFront<TypeList<Head, Tails...>>
{
private:
    using TheMostDerived = typename MostDerived<TypeList<Head, Tails...>, Head>::Result;
    using Temp = typename Replace<TypeList<Tails...>, TheMostDerived, Head>::Result;
public:
    using Result = typename Append<TypeList<TheMostDerived>, Temp>::Result;
};  

About

Reference to Chapter 3. Typelists In Modern C++ Design and implement with c++17

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published