c++variadic-templatestypelist

C++ typelist make sublist


Let's says I have a type

template<typename ...Ts>
struct typelist {};

I need to get a sublist from this list :

template<int startInclusive, int stopExclusive, typename ...Ts>
struct sublist {
    using type = ?; //
};

for example

sublist<1, 3, int, float, double, char>::type == typelist<float, double>

When start = 0 I have a working tail implementation :

template<typename ...Ts>
struct typelist {};

template<int N, typename T, typename ...Ts>
struct tail {
    using type = typename tail<N - 1, Ts...>::type;
};

template<typename T, typename ...Ts>
struct tail<0, T, Ts...> {
    using type = typelist<T, Ts...>;
};

using T = tail<1, int, double>::type;

#include <typeinfo>
#include <cstdio>

int main() {
   ::printf("%s\n", typeid(T).name());
}

However, I cannot get anything working for start > 0


Solution

  • It's likely to be an overkill, but it works:

    template<typename... Ts>
    struct typelist {};
    
    template<class Typelist, typename T>
    struct prepend;
    
    template<typename... Ts, typename T>
    struct prepend<typelist<Ts...>, T> {
        using type = typelist<T, Ts...>;
    };
    
    template<int start, int stop, int i, typename... Ts>
    struct sublist_impl {
        using type = typelist<>;
    };
    
    template<int start, int stop, int i, typename T, typename... Ts>
    struct sublist_impl<start, stop, i, T, Ts...>
    {
    private:
        static constexpr auto get_sublist_type() {
            if constexpr (i < start)
                return typename sublist_impl<start, stop, i + 1, Ts...>::type{};
            else if constexpr (i < stop)        
                return typename prepend<typename sublist_impl<
                    start, stop, i + 1, Ts...>::type, T>::type{};
            else
                return typelist<>{};
        }
    
    public:
        using type = decltype(get_sublist_type());
    };
    
    template<int start, int stop, typename... Ts>
    struct sublist {
        using type = typename sublist_impl<start, stop, 0, Ts...>::type;
    };
    
    template<int start, int stop, typename... Ts>
    using sublist_t = typename sublist<start, stop, Ts...>::type;
    
    static_assert(std::is_same_v<
        sublist_t<1, 3, int, float, double, char>, typelist<float, double>>);
    
    static_assert(std::is_same_v<
        sublist_t<0, 0, int, float, double, char>, typelist<>>);
    
    static_assert(std::is_same_v<
        sublist_t<4, 4, int, float, double, char>, typelist<>>);
    
    static_assert(std::is_same_v<
        sublist_t<0, 3, int, float, double, char>, typelist<int, float, double>>);
    
    static_assert(std::is_same_v<
        sublist_t<0, 4, int, float, double, char>, typelist<int, float, double, char>>);