Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a sub-tuple starting from a std::tuple<some_types...>

Let us suppose that a std::tuple<some_types...> is given. I would like to create a new std::tuple whose types are the ones indexed in [0, sizeof...(some_types) - 2]. For instance, let's suppose that the starting tuple is std::tuple<int, double, bool>. I would like to obtain a sub-tuple defined as std::tuple<int, double>.

I'm quite new to variadic templates. As a first step I tried to write a struct in charge of storing the different types of the original std::tuple with the aim of creating a new tuple of the same kind (as in std::tuple<decltype(old_tuple)> new_tuple).

template<typename... types>
struct type_list;

template<typename T, typename... types>
struct type_list<T, types...> : public type_list<types...>  {
    typedef T type;
};


template<typename T>
struct type_list<T> {
    typedef T type;
};

What I would like to do is something like:

std::tuple<type_list<bool, double, int>::type...> new_tuple // this won't work

And the next step would be of discarding the last element in the parameter pack. How can I access the several type's stored in type_list? and how to discard some of them?

Thanks.

like image 368
Ilio Catallo Avatar asked Jul 25 '13 09:07

Ilio Catallo


1 Answers

Here is a way to solve your problem directly.

template<unsigned...s> struct seq { typedef seq<s...> type; };
template<unsigned max, unsigned... s> struct make_seq:make_seq<max-1, max-1, s...> {};
template<unsigned...s> struct make_seq<0, s...>:seq<s...> {};

template<unsigned... s, typename Tuple>
auto extract_tuple( seq<s...>, Tuple& tup ) {
  return std::make_tuple( std::get<s>(tup)... );
}

You can use this as follows:

std::tuple< int, double, bool > my_tup;
auto short_tup = extract_tuple( make_seq<2>(), my_tup );
auto skip_2nd = extract_tuple( seq<0,2>(), my_tup );

and use decltype if you need the resulting type.

A completely other approach would be to write append_type, which takes a type and a tuple<...>, and adds that type to the end. Then add to type_list:

template<template<typename...>class target>
struct gather {
  typedef typename type_list<types...>::template gather<target>::type parent_result;
  typedef typename append< parent_result, T >::type type;
};

which gives you a way to accumulate the types of your type_list into an arbitrary parameter pack holding template. But that isn't required for your problem.

like image 125
Yakk - Adam Nevraumont Avatar answered Oct 13 '22 17:10

Yakk - Adam Nevraumont