If you want to do metaprogramming, start working with types. If you want non-piggy type template parameters, move them to types as soon as possible.
Below I first take Pack<1,2,3> and convert it to types< std::integral_constant<int, 1>, std::integral_constant<int, 2>, std::integral_constant<int, 3> > . This is a list of types that explicitly matches your ints package.
Then I introduce a tag type template. This is a type that βcarriesβ another type, but it does not have citizenship. You can extract the type from the value of the template instance as a bonus.
Thirdly, I write a function "for each type", which takes a lambda and a package of types, and proceeds to call a lambda once for each type, passing the type of tag.
In the body of a lambda, we can extract the passed type using decltype in the tag variable (or helper macro).
We combine them together, and from the resulting tag we can extract an integer in the source package.
As a result, you can enter this in your code:
for_each_type( [&](auto tag){ constexpr int i = TAG_TYPE(tag){}; // use i }, ints_as_types_t<ints>{} );
in the middle of your method and work with ints "inline".
If we only decided to solve your specific problem, we would make a little less template, but I liked the pedigree.
template<class...>struct types{using type=types;}; template <int...Is> struct Pack {}; template<class pack> struct ints_as_types; template<class pack> using ints_as_types_t=typename ints_as_types<pack>::type; template<class T, template<T...>class pack, T...ts> struct ints_as_types<pack<ts...>> { using type=types<std::integral_constant<T,ts>...>; };
now we can do:
using pack = ints_as_types_t<Pack<1,2,3>>;
and pack is a list of types, not a list of integers.
Now some meta-programming in khana style: (metaprogramming with values ββinstead of pure types)
template<class T>struct tag_t{using type=T; constexpr tag_t(){};}; template<class T>constexpr tag_t<T> tag={}; template<class Tag>using type_t=typename Tag::type; #define TAG_TYPE(...) type_t<std::decay_t<decltype(__VA_ARGS__)>>; template<class F, class...Ts> void for_each_type(F&& f, types<Ts...>) { using discard=int[]; (void)discard{ 0, (( f(tag<Ts>) ),void(),0)...}; }
which allows you to iterate over a set of types.
for_each_type( [&](auto tag){ constexpr int i = TAG_TYPE(tag){}; // use i }, ints_as_types_t<ints>{} );
gives you a lambda that has constexpr int i for each of the types in your list.
A letter from the above work raises your ints list into a list of types, because working with only types makes metaprogramming less special. You can skip this climb and write for_each_integer , which takes Pack<int...> directly with less code, but it seems less useful to me.