Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic Template Parameter Packs with Alternating Types

I was wondering if it is possible to capture an alternating parameter pattern using a parameter pack. For example,

template<typename T, size_t U, typename... Args>
class foo<T, U, Args...>
{
   public:
     foo() : my_T(nullptr), my_U(U) {}

   private:
     T* my_T;
     size_t my_U;
     foo<Args...> my_next_foo;
}

So this doesn't work since Args is a parameter pack of only types. Is there a way to modify this so that the typename T, size_t U pattern can be properly captured in a variadic template? Thanks


2 Answers

Values as template parameters are second class citizens, in my experience.

Upgrade them to first class with an alias:

template<std::size_t n>
using size = std::integral_constant<std::size_t, n>;

then pattern match:

template<class...>
struct foo;
template<>
struct foo<> {
  // empty
};
template<class T, size_t U, typename... Args>
struct foo<T, size<U>, Args...> {
  foo() : my_T(nullptr), my_U(U) {}

private:
  T* my_T;
  size_t my_U;
  foo<Args...> my_next_foo;
};

and bob is your uncle.

Note, however, that taking U as a template parameter, then storing it as a run time value, is highly questionable.

Users of foo must do:

foo< Chicken, size<3>, Dog, size<17> >

instead of

foo< Chicken, 3, Dog, 17 >
like image 123
Yakk - Adam Nevraumont Avatar answered Oct 23 '25 06:10

Yakk - Adam Nevraumont


Sure, just write your own pair:

template <typename T, size_t U>
struct foo_pair { };

And have a pack of those:

template<typename T, size_t U, typename... Pairs>
class foo<foo_pair<T, U>, Pairs...> {
    ...
};

Which would be instantiated like:

foo<foo_pair<int, 4>, foo_pair<char, 17>, ...> f;
like image 31
Barry Avatar answered Oct 23 '25 08:10

Barry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!