NaCl NaCl - 1 month ago 7
C++ Question

Is it possible to convert a list of `integral_constant`s back to a list of `T`'s?

I managed to convert a

template<int ...Args> struct List
to a list of
integral_constant
's, however, is it possible to convert from
integral_constant
's back to
int
s?

Here is how I do the conversion from
IntList
to
List
:

template<typename ...Args>
struct List;

template<typename T>
struct ListFromTupleImpl;
template<typename ...Args>
struct ListFromTupleImpl<std::tuple<Args...>>
{ using type = List<Args...>; };

template<typename T>
using ListFromTuple = typename ListFromTupleImpl<T>::type;
template<typename ...Args>
using TupleCat = decltype(std::tuple_cat(std::declval<Args>()...));
template<typename ...Args>
using ListFromTupleCat = ListFromTuple<TupleCat<Args...>>;

template<int ...Args>
struct IntList;

template<typename ...Args>
struct List
{
template<typename T>
struct Concat;
template<typename ...Args0>
struct Concat<List<Args0...>>
{
using type = ListFromTupleCat<std::tuple<Args...>,
std::tuple<Args0...>>;
};
};

template<int ...Args>
struct IntList
{
template<int first, int ...Args0>
struct ListBuilder
{
using type = typename List<std::integral_constant<int, first>>::
template Concat<typename ListBuilder<Args0...>::type>::type;
};
template<int last>
struct ListBuilder<last>
{
using type = List<std::integral_constant<int, last>>;
};
using asList = typename ListBuilder<Args...>::type;
};

Answer

You can do what you want by letting the compiler match template patterns:

template<typename... Ts>
auto to_int_list_helper(List<Ts...>) {
    return IntList<Ts::value...>{};
}

template<typename ListParam>
using AsIntList = decltype(to_int_list_helper(ListParam{}));

and a proof of concept:

using L = typename IntList<1,2>::asList;

static_assert(is_same<L, List<integral_constant<int, 1>, integral_constant<int, 2>>>::value, "");

using BackToIntList = AsIntList<L>;

static_assert(is_same<IntList<1,2>, BackToIntList>::value, "");

live demo

Since you also asked about concatenation, it's really simple to leverage the same technique:

template<int... Ts, int... Us>
auto concat_int_lists_helper(IntList<Ts...>, IntList<Us...>) {
    return IntList<Ts..., Us...>{};
}

template<typename A, typename B>
using ConcatIntLists = decltype(concat_int_lists_helper(A{}, B{}));

live demo