Another solution could be:
#include <tuple>
#include <utility>
#include <functional>
#include <type_traits>
template <size_t N, class R, class Pack, class ResultPack, class Voider>
struct FuncTypeImpl;
template <size_t N, class R, template <class...> class Pack, class First, class... Args, class... ResultArgs>
struct FuncTypeImpl<N, R, Pack<First, Args...>, Pack<ResultArgs...>, std::enable_if_t<(N > 0)>>: FuncTypeImpl<N-1, R, Pack<Args...>, Pack<ResultArgs..., First>, void> {
using typename FuncTypeImpl<N-1, R, Pack<Args...>, Pack<ResultArgs..., First>, void>::Type;
};
template <size_t N, class R, template <class...> class Pack, class... Args, class... ResultArgs>
struct FuncTypeImpl<N, R, Pack<Args...>, Pack<ResultArgs...>, std::enable_if_t<(N == 0)>> {
using Type = std::function<R(ResultArgs...)>;
};
template<std::size_t, typename>
struct FuncType;
template<std::size_t N, typename R, typename... A>
struct FuncType<N, R(A...)> {
using Type = typename FuncTypeImpl<N, R, std::tuple<A...>, std::tuple<>, void>::Type;
};
int main() {
static_assert(
std::is_same<
FuncType<3, void(int, char, double, int)>::Type,
std::function<void(int, char, double)>
>::value,
"!"
);
}
Edit:
Yet another maybe a little bit simpler (that does not need a std::tuple) solution:
#include <utility>
#include <functional>
#include <type_traits>
template <class T>
struct ResultOf;
template <class R, class... Args>
struct ResultOf<R(Args...)> {
using Type = R;
};
template<std::size_t N, class Foo, class ResultFoo = typename ResultOf<Foo>::Type() , class Voider = void>
struct FuncType;
template<std::size_t N, class R, class First, class... Args, class... ResultArgs >
struct FuncType<N, R(First, Args...), R(ResultArgs...), std::enable_if_t<(N > 0)>>: FuncType<N-1, R(Args...), R(ResultArgs..., First), void> {
};
template<std::size_t N, class R, class First, class... Args, class... ResultArgs >
struct FuncType<N, R(First, Args...), R(ResultArgs...), std::enable_if_t<(N == 0)>> {
using Type = std::function<R(ResultArgs...)>;
};
int main() {
static_assert(
std::is_same<
FuncType<3, void(int, char, double*, int)>::Type,
std::function<void(int, char, double*)>
>::value,
"!"
);
}