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
As usual, std::index_sequence
helps here:
template <std::size_t Offset, typename Seq, typename Tuple> struct sublist_impl;
template <std::size_t Offset, std::size_t ... Is, typename Tuple>
struct sublist_impl<Offset, std::index_sequence<Is...>, Tuple>
{
using type = std::tuple<std::tuple_element_t<Offset + Is, Tuple>...>;
};
template<std::size_t startInclusive, std::size_t stopExclusive, typename ...Ts>
using sublist = typename sublist_impl<startInclusive,
std::make_index_sequence<stopExclusive - startInclusive>,
std::tuple<Ts...>>::type;
Demo
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>>);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With