9

I have the following problem:

template< std::size_t N >
class A
{
  std::function< std::size_t( /*std::size_t,....,std::size_t <- N-times*/) > foo;
};

As you can see above, I try to declare an std::function<...> foo as a member of a class A. Here, I want foo to have the return type std::size_t (which is no problem) and as input, I will pass N-times the type std::size_t but I don't know how. Is there any possibility?

Many thanks in advance.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
abraham_hilbert
  • 2,221
  • 1
  • 13
  • 30

3 Answers3

16

You can use std::index_sequence:

template<std::size_t N, typename = std::make_index_sequence<N>>
struct A;

template<std::size_t N, std::size_t... S>
struct A<N, std::index_sequence<S...>> {
    std::function<std::size_t(decltype(S)...)> foo;
};

Live example

If you like, you could also define to what type it expands:

template<typename T, std::size_t N, typename = std::make_index_sequence<N>>
struct A;

template<typename T, std::size_t N, std::size_t... S>
struct A<T, N, std::index_sequence<S...>> {
    template<std::size_t>
    using type = T;

    std::function<std::size_t(type<S>...)> foo;
};
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • 1
    great solution. Cleaner than mine. – bolov Oct 12 '16 at 14:42
  • For those struggling to find the definition: `std::index_sequence` is a helper alias defined in `` as a "[helper alias template \[of `std::integer_sequence`\] for the common case where `T` is `std::size_t`](http://en.cppreference.com/w/cpp/utility/integer_sequence#Helper_templates)." – Toby Speight Oct 12 '16 at 16:04
  • And then for something a little more general you could have a `template using make_type_wrapper = T;` That way if you wanted something other than `size_t` as the signature you could use that wrapper instead – SirGuy Nov 18 '16 at 19:20
4

For arbitrary type and not just size_t, just write a helper alias:

template<class T, size_t>
using Type = T;

template<std::size_t... S>
struct AHelper<std::index_sequence<S...>> {
    std::function<size_t(Type<MyArbitraryTypeHere, S>...)> foo;
};
T.C.
  • 133,968
  • 17
  • 288
  • 421
1

Ok this was fun. Here is my solution:

namespace details {
template <size_t N, class F = size_t()>
struct Function_type_helper {};

template <size_t N, class... Args>
struct Function_type_helper<N, size_t(Args...)> {
    using Type = typename Function_type_helper<N - 1, size_t(Args..., size_t)>::Type;
};

template <class... Args>
struct Function_type_helper<0, size_t(Args...)> {
    using Type = size_t(Args...);
};

template <size_t N, class F = size_t()>
using Function_type_helper_t = typename Function_type_helper<N, F>::Type;

static_assert(std::is_same_v<Function_type_helper_t<3>, size_t(size_t, size_t, size_t)>);
} // ns details

template<size_t N>
struct A
{
  std::function<details::Function_type_helper_t<N>> foo;
};

This works by recursively creating the type size_t(size_t, size_t, ..., size_t)

For instance:

H<3>::Type == H<3, size_t()>::Type ==
              H<2, size_t(size_t)>::Type == 
              H<1, size_t(size_t, size_t)>::Type ==
              H<0, size_t(size_t, size_t, size_t)>::Type ==
              size_t(size_t, size_t, size_t)
bolov
  • 72,283
  • 15
  • 145
  • 224