Okay, so I thought I was going to die, but I finally managed to do it Γ§_Γ§
Firstly, I used regular indexes. Since I don't have official ones, I used old indexes that I wrote a few months ago:
template<std::size_t...> struct indices {}; template<std::size_t N, std::size_t... Ind> struct make_indices: make_indices<N-1, N-1, Ind...> {}; template<std::size_t... Ind> struct make_indices<0, Ind...>: indices<Ind...> {};
Then I used some function properties found somewhere in StackOverflow. They are nice, and I think they are equivalent to the Boost library associated with comments:
template<typename T> struct function_traits: function_traits<decltype(&T::operator())> {}; template<typename C, typename Ret, typename... Args> struct function_traits<Ret(C::*)(Args...) const> { enum { arity = sizeof...(Args) }; using result_type = Ret; template<std::size_t N> using arg = typename std::tuple_element<N, std::tuple<Args...>>::type; };
Then I was able to write the correct make_foo
function and its implementation function, since both should use indexes. Be careful, this is just ugly:
template<typename Function, std::size_t... Ind> auto make_foo_(Function&& func, indices<Ind...>) -> Foo< typename function_traits<typename std::remove_reference<Function>::type>::result_type, typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...> { using Ret = typename function_traits<typename std::remove_reference<Function>::type>::result_type; return { std::function<Ret(typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...)>(func) }; } template<typename Function, typename Indices=make_indices<function_traits<typename std::remove_reference<Function>::type>::arity>> auto make_foo(Function&& func) -> decltype(make_foo_(std::forward<Function>(func), Indices())) { return make_foo_(std::forward<Function>(func), Indices()); }
The code is somehow ugly and unreadable, but it definitely works. I hope that now he does not rely on any specific behavior. Also, thanks for your advice, it helped! :)
int main() { auto lambda = [](int i, float b, long c) { return long(i*10+b+c); }; auto foo = make_foo(lambda); std::cout << foo(5, 5.0, 2) << std::endl;
And here is a living example :)