3

I need a tricky thing in a C++ 2011 code. Currently, I have a metafunction of this kind :

template<unsigned int N, unsigned int M> 
static constexpr unsigned int myFunction()

This function can generate number based on N and M.

I would like to write a metafunction with input N and M, and that will recursively construct a variadic template by decrementing M. For example, by calling this function with M = 3, It will construct a variadic template called List equal to :

List... = myFunction<N, 3>, myFunction<N, 2>, myFunction<N, 1>, myFunction<N, 0>

How to do that (if it is possible of course) ?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Vincent
  • 57,703
  • 61
  • 205
  • 388
  • 1
    it would be better if you tell the use case i.e how you're going to use it . also simply function name `myFunction` means nothing without parenthesis.A more elaborated example with use case would be helpful – Mr.Anubis Sep 05 '12 at 20:58

1 Answers1

4

It's probably simplest to use an existing tuple pack generator:

// Idiomatic tuple pack generator using successor method
template<int... I> struct tuple_pack {
    using succ = tuple_pack<I..., sizeof...(I)>;
};
template<int N> struct make_tuple_pack {
    using type = typename make_tuple_pack<N - 1>::type::succ;
};
template<> struct make_tuple_pack<0> {
    using type = tuple_pack<>;
};

Now we can apply the tuple pack generator, delegating to an implementation function:

template<int N, int M, typename T> struct foo_impl {};
template<int N, int M, int... I> struct foo_impl<N, M, tuple_pack<I...>> {
    static void foo() {
        int arr[M] = { myFunction<N, M - I>()... };
    }
};
template<int N, int M> void foo() {
    foo_impl<N, M, typename make_tuple_pack<M>::type>::foo();
}

If you prefer function parameter inference to class template specialisation this could also be written as:

template<int N, int M, int... I> void foo_impl(tuple_pack<I...>) {
    int arr[M] = { myFunction<N, M - I>()... };
}
template<int N, int M> void foo() {
    foo_impl<N, M>(typename make_tuple_pack<M>::type{});
}

I had to specify the array size as int arr[M]; not sure whether that's required by the standard for pack expansion initializers or whether it's a bug in gcc; either way it's no big hassle.

ecatmur
  • 152,476
  • 27
  • 293
  • 366