Reversing Template Parameters on Templated Types

When I came across this Stack Overflow question about reversing a c++ std::tuple type, naturally I wondered if the same could be done to templated types besides std::tuple, i.e. for a templated type T, converting T<P1, P2, ..., Pn> to T<Pn, Pn-1, ..., P1>.

Not that I have any practically application for type reversal mind you. But I was curious.

Templated Type Template Parameter Combinations and Permutations

Before implementing type reversal, we need to understand templated type permutations and combinations. We ultimately only care about the reversed type permutation, but getting there requires a number of intermediate type combinations. And some of these combinations may not be valid instantiations of T.

With a set of parameters std::tuple<P1, P2, ..., Pn>, the std::tuple type is valid for any combination or permutation of P1, P2, ..., Pn.

// For a target tuple
usingmy_tuple=std::tuple<int,bool,std::string>;// All permutations and combination are also valid:
std::tuple<int,bool,std::string>;std::tuple<int,std::string,bool>;std::tuple<bool,int,std::string>;std::tuple<bool,std::string,int>;std::tuple<std::string,int,bool>;std::tuple<std::string,bool,int>;std::tuple<int,bool>;std::tuple<int,std::string>;std::tuple<bool,int>;std::tuple<bool,std::string>;std::tuple<std::string,int>;std::tuple<std::string,bool>;std::tuple<int>;std::tuple<bool>;std::tuple<std::string>;std::tuple<>;

But std::tuple is actually the exception in this respect. Most types, even std::pair, are only valid for specific permutations and combinations.

Although our ultimate goal is to determine the revered type permutation, the most simple type reversal logic requires a number of intermediate combination types, all of which must be valid, to calculate the final reversed types.

Easy Case - Reversing Tuple-Like Types

We’ll therefore start by reversing a std::tuple. This way, we don’t have to worry about invalid type combinations and permutations. The second part of this post will apply reversal to any templated type.

To start, we need a helper to get the base case of type reversal, templated type T with zero parameters.

The reversal implementation itself is based on this Stack Overflow answer, generalized to template type T. reverse_impl operates on two templated types: an input type T<...> that captures the rest of the type list to be reversed and an output type T<...> that captures the reversed type output.

This is because reverse_impl attempts to instantiate std::pair with invalid template parameters, such as std::pair<>. So even though we technically never use these intermediate types for anything more than storing a list of types, the compiler does not know this. We need another level of indirection to reverse arbitrary types where only the input and reversed type permutation must be valid.

The goal here is to make any templated type T behave like a std::tuple. In fact, we really just need to put the types of T into a std::tuple, reverse the tuple, and then extract and reapply the reversed types back to T.

To avoid confusion, I’ll define a template type type_list that captures a list of types, much the way std::tuple does.

template<typename...>structtype_list{};/// Helper the creates a type list from a templated type.
template<typename>structmake_type_list;template<template<typename...>classT,typename...TArgs>structmake_type_list<T<TArgs...>>{usingtype=type_list<TArgs...>;};

This allows us to put a templated type type list into a type_list type that can be reversed.

/// Standard collections cannot be directly reversed easily
/// because they take default template parameters such as Allocator.
template<typenameK,typenameV>structsimple_map:std::unordered_map<K,V>{};std::is_same<typenamereverse_type<simple_map<std::string,int>>::type,simple_map<int,std::string>>::value;

Conclusion

Like most good template metaprogramming, I have no clue how type reversal can be practically applied. But it is possible, and implementing it did significantly improve my understanding of the c++ template system.