How do I reverse the types in a tuple? For example, I want reverse_tuple<std::tuple<int, char, bool>>::type
to be std::tuple<bool, char, int>
. I tried doing the following but it didn't work. What did I do wrong?
#include <type_traits>
#include <tuple>
template <typename... Ts>
struct tuple_reverse;
template <typename T, typename... Ts>
struct tuple_reverse<std::tuple<T, Ts...>>
{
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
};
template <typename T>
struct tuple_reverse<std::tuple<T>>
{
using type = std::tuple<T>;
};
int main()
{
using result_type = std::tuple<int, bool, char>;
static_assert(
std::is_same<
tuple_reverse<var>::type, std::tuple<char, bool, int>
>::value, ""
);
}
Here are my errors:
prog.cpp: In instantiation of ‘struct tuple_reverse<std::tuple<char, int, bool> >’:
prog.cpp:15:34: recursively required from ‘struct tuple_reverse<std::tuple<bool, char, int> >’
prog.cpp:15:34: required from ‘struct tuple_reverse<std::tuple<int, bool, char> >’
prog.cpp:29:31: required from here
prog.cpp:15:34: error: no type named ‘type’ in ‘struct tuple_reverse<std::tuple<int, bool, char> >’
prog.cpp: In function ‘int main()’:
prog.cpp:30:9: error: template argument 1 is invalid
I came across this question while working on the reversing template parameters for arbitrary types.
Jonathan Wakely's answer works great for tuples but in case anyone else ever needs to reverse any type, i.e.
T<P1, P2, ..., Pn>
toT<Pn, Pn-1, ..., P1>
, here is what I came up with (Reversal logic taken from here).Some of the implementation logic can be combined, but I tried to make it as clear as possible here.
reverse_type
can be applied to tuples:Or other types:
Slightly more detailed explanation.
Untested.
Something there abouts anyway.
This also only reverses the type, which seems to be what you're after. Reversing an actual tuple would involve functions, not metafunctions.
Out of interest, did you really want to reverse a tuple type, or just treat each element in reverse order (as is more often the case in my projects)?
What you did wrong was here:
Looking at it from the inside out, you reorder the tuple elements:
tuple<Ts..., T>
, then you try to reverse that, then you put the result in atuple
, then you try to reverse that ... huh?! :)This means each time you instantiate
tuple_reverse
you give it a tuple of the same size, so it never finishes, and recursively instantiates itself forever. (Then, if that recursion even finished, you put the resulting tuple type into a tuple, so you have a single-element tuple containing an N-element tuple, and reverse that, which does nothing because reversing a single-element tuple is a no-op.)You want to peel off one of the elements, then reverse the rest, and concatenate it back again:
And you don't need to wrap it in a tuple and reverse it again :)
And you should also handle the empty tuple case, so the whole thing is:
I'd do it differently though.
To get just the type, using C++14
Or you can write a function to reverse an actual tuple object, then use
decltype(reverse(t))
to get the type. To reverse a tuple-like object in C++14:In C++11 use
<integer_seq.h>
and add return types and useremove_reference
to strip references from the tuple type (becausetuple_size
andtuple_element
don't work with references to tuples):