1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| #include <iostream> #include <utility> #include <vector>
namespace util { template <typename ReturnType, typename... Args> struct function_traits_defs { static constexpr size_t arity = sizeof...(Args);
using result_type = ReturnType;
template <size_t i> struct arg { using type = typename std::tuple_element<i, std::tuple<Args...>>::type; }; };
template <typename T> struct function_traits_impl;
template <typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(Args...)> : function_traits_defs<ReturnType, Args...> {};
template <typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(*)(Args...)> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...)> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&&> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&&> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&> : function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args> struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&&> : function_traits_defs<ReturnType, Args...> {};
template <typename T, typename V = void> struct function_traits : function_traits_impl<T> {};
template <typename T> struct function_traits<T, decltype((void)&T::operator())> : function_traits_impl<decltype(&T::operator())> {};
template <size_t... Indices> struct indices { using next = indices<Indices..., sizeof...(Indices)>; }; template <size_t N> struct build_indices { using type = typename build_indices<N - 1>::type::next; }; template <> struct build_indices<0> { using type = indices<>; }; template <size_t N> using BuildIndices = typename build_indices<N>::type;
namespace details { template <typename FuncType, typename VecType, size_t... I, typename Traits = function_traits<FuncType>, typename ReturnT = typename Traits::result_type> ReturnT do_call(FuncType& func, const VecType& args, indices<I...>) { return func(args[I]...); } }
template <typename FuncType, typename VecType, typename Traits = function_traits<FuncType>> auto unpack_caller(FuncType& func, const VecType& args) { return details::do_call(func, args, BuildIndices<Traits::arity>()); } }
int func(int a, int b, int c) { return a + b + c; }
int main() { std::vector<int> args = {1, 2, 3};
int j = util::unpack_caller(func, args); std::cout << j << std::endl;
return 0; }
|