1

Coming from this earlier question on finding the number of unique values of a parameter pack, has made me think, if it is feasible to pass/forward a selected number of variadic parameter pack to another function or to return them, for instance, assume we have a struct that takes a homogeneous pack

template<size_t ... Rest>
struct my_struct;

I would like to have a function foo that takes this parameter pack and returns another struct with unique values of the parameter pack passed to it, something like

template<size_t N, size_t ... Rest>
my_struct<uniques<N,Rest...>> foo(const my_struct<N,Rest...> &a) {
// do stuff
}

As an example:

my_struct<0,5,2,0,4,2> a;
my_struct<0,5,2,4> b = foo(a);

Sorting the values, is not of any interest here. Is this functionality possible to achieve using only the standard library?

Community
  • 1
  • 1
romeric
  • 2,325
  • 3
  • 19
  • 35

1 Answers1

3

Just wrap uniques in another metafunction. Just building off of my last answer:

template <class T, template <T...> class Z>
struct quote_c {
    template <class... Ts>
    using apply = Z<Ts::value...>;
};

template <class MFC, class TL>
struct apply_typelist;

template <class MFC, class TL>
using apply_typelist_t = typename apply_typelist<MFC, TL>::type;


template <class MFC, class... Ts>
struct apply_typelist<MFC, typelist<Ts...>> {
    using type = typename MFC::template apply<Ts...>;
};

Now we have a metafunction class version of my_struct, and a metafunction that takes a metafunction class and a typelist and jams them together.

So now it's just:

template <class T, T... Vals>
using typelist_c = typelist<std::integral_constant<T, Vals>...>;

template <size_t N,
          size_t ... Rest,
          class R = apply_typelist_t<quote_c<size_t, my_struct>,
                        uniq_t<typelist_c<size_t, N, Rest...>>>
          >
R foo(const my_struct<N,Rest...> &a) {
    // ...
}

To work through your example of <0,5,2,0,4,2>.

  1. First, we wrap all those numbers into types to get a typelist<0i,5i,2i,0i,4i,2i> (I'm just using i as shorthand to mean that it's a std::integral_constant).
  2. Next we wrap that in uniq_t, which produces typelist<0i,5i,2i,4i>.
  3. Next, we pass that into apply_typelist which gives us the type quote_c<size_t, my_struct>::apply<0i, 5i, 2i, 4i>
  4. Which itself is an alias for my_struct<0, 5, 2, 4>, as desired.
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977