Notice: Followup to this question
After asking this question about parameter pack folding into pairs, I noticed that I need to retain the complete type of the previously folded type as the left pair type.
For example:
Fold<char, int, long, double> f;
must evaluate to
std::tuple<
std::pair<char
, int>,
std::pair<std::pair<char, int> /* <-- the previous resulting type */
, long>,
std::pair<std::pair<std::pair<char, int>, long> /* the previous type again */
, double>
> f;
Context to this problem
The reason why I need this, is because the types which have to be "folded" can be placeholder types. The placeholders "real" type can only be known when both having the fully expanded type to the left as well as the unexpanded type. The leftmost type never contains placeholders.
Let me illustrate this with a quick example:
struct CopyTypeFromPreviousArgumentTag { };
template<typename T = CopyTypeFromPreviousArgumentTag>
struct Foo;
template<typename T...>
struct Bar {
/* Here fold will not use std::pair, but a resolver type that takes both A and B and gives back the resolved B */
Fold<T...> expanded;
};
Now Bar
can be used like this:
Bar< Foo<int>
, Foo<>
, Foo<>
, Foo<double>
, Foo<>
> f;
and the internal type decltype(f::expanded)
will be:
std::tuple< Foo<int>
, Foo<int>
, Foo<int>
, Foo<double>
, Foo<double>
>;
EDIT: The Bar
class is actually not restricted to any class type it might hold. It can be a mixture of several types. So see the Foo
class as a placeholder for some type Foo
where a resolver type traits exists given the previous resolved type: ResolveType<PreviouslyResolvedType, CurrentType>::Type
will give the resolved type correctly. Hence the std::pair
idiom.
My current attempt
I tried to implement the recursion by building upon the answer from the linked question, but can't get it to work.
namespace Detail {
template<typename, typename...>
struct Fold;
template
< size_t... Indices
, typename... Types
> struct Fold<std::index_sequence<Indices...>, Types...> {
using Tuple = std::tuple<Types...>;
using Type = std::tuple<std::pair /* use std::pair just to match the first example */
//< std::tuple_element_t<Indices, Tuple>
< typename Fold
< std::tuple_element_t<Indices, Tuple>
, std::make_index_sequence<Indices>
, Types...>::Type; /* Tuple can't be expanded :( */
, std::tuple_element_t<Indices + 1, Tuple>
>::Type...>;
};
} /* namespace Detail */
template<typename... Types>
using Fold = typename Detail::Fold<std::make_index_sequence<sizeof...(Types) - 1>, Types...>::Type;