diff --git a/include/functional_unwrap.hpp b/include/functional_unwrap.hpp index 1be4613..ff0e5c3 100644 --- a/include/functional_unwrap.hpp +++ b/include/functional_unwrap.hpp @@ -30,10 +30,32 @@ namespace fu { - /// Identity class which is used to carry parameter packs. + /// Identity class which is used to carry parameter packs of types. template struct identity { }; + /// Sequence class which is used to carry parameter packs of unsigned integers. + template + struct sequence { }; + + /// The Sequence generator generates a sequence of numbers with the given size. + template + struct sequence_generator; + + template + struct sequence_generator<0, Stack...> + { + typedef sequence type; + }; + + template + struct sequence_generator + : public sequence_generator { }; + + /// Sequence generator alias + template + using sequence_of_t = typename sequence_generator::type; + namespace detail { template @@ -55,6 +77,11 @@ namespace fu typedef _RTy(*function_ptr)(_ATy...); }; + /// Pack in fu::identity + template + struct unwrap_function_impl> + : unwrap_function_impl<_RTy(_ATy...)> { }; + /// STL: std::function template struct unwrap_function_impl> @@ -85,11 +112,6 @@ namespace fu struct unwrap_function_impl<_RTy(_CTy::*)(_ATy...)> : unwrap_function_impl<_RTy(_ATy...)> { }; - /// Pack in fu::identity - template - struct unwrap_function_impl> - : unwrap_function_impl<_RTy(_ATy...)> { }; - /// Unwrap through pointer of functor. template static auto select_best_unwrap_unary_arg(int) @@ -188,6 +210,38 @@ namespace fu typedef T type; }; + namespace detail + { + /// Implementation of invoke_with_tuple + template + struct invoker; + + template + struct invoker> + { + template + static auto invoke(_FTy&& functional, _TTy&& tuple) + -> ::fu::return_type_of_t::type> + { + return std::forward<_FTy>(functional)(std::get(std::forward<_TTy>(tuple))...); + } + }; + } + + /// Invokes a function type with the given tuple arguments. + template + inline auto invoke_with_tuple(_FTy&& functional, _TTy&& tuple) + -> return_type_of_t::type> + { + return detail::invoker< + sequence_of_t< + std::tuple_size< + typename std::decay<_TTy>::type + >::value + > + >::invoke(std::forward<_FTy>(functional), std::forward<_TTy>(tuple)); + } + } // fu #endif // _FUNCTIONAL_UNWRAP_HPP_ diff --git a/test.cpp b/test.cpp index 559315a..9feea1c 100644 --- a/test.cpp +++ b/test.cpp @@ -82,6 +82,8 @@ Continuable&&> MoveTest() }); } +typedef std::unique_ptr Moveable; + void testMoveAbleNormal(std::function&&)> callback) { std::unique_ptr ptr(new int(5)); @@ -93,6 +95,43 @@ void test_unwrap(std::string const& msg) { std::cout << msg << " is unwrappable: " << (fu::is_unwrappable::value ? "true" : "false") << std::endl; } +/* +template +struct Apply { + template + static inline auto apply(F && f, T && t, A &&... a) + -> decltype(Apply::apply( + ::std::forward(f), ::std::forward(t), + ::std::get(::std::forward(t)), ::std::forward(a)... + )) + { + return Apply::apply(::std::forward(f), ::std::forward(t), + ::std::get(::std::forward(t)), ::std::forward(a)... + ); + } +}; + +template<> +struct Apply<0> { + template + static inline auto apply(F && f, T &&, A &&... a) + -> decltype(::std::forward(f)(::std::forward(a)...)) + { + return ::std::forward(f)(::std::forward(a)...); + } +}; + +template +inline auto apply(F && f, T && t) + -> decltype(Apply< ::std::tuple_size< + typename ::std::decay::type + >::value>::apply(::std::forward(f), ::std::forward(t))) +{ + return Apply< ::std::tuple_size< + typename ::std::decay::type + >::value>::apply(::std::forward(f), ::std::forward(t)); +} +*/ int main(int /*argc*/, char** /*argv*/) { @@ -281,6 +320,23 @@ int main(int /*argc*/, char** /*argv*/) std::tuple> tup; + Moveable moveable(new int(7)); + + auto myargs = std::make_tuple(7, std::vector({ 1, 2, 3 }), std::move(moveable)); + + std::function, Moveable&&)> lam = [](int given_i, std::vector given_vec, Moveable&& moveable) + { + Moveable other = std::move(moveable); + + ++given_i; + return 1; + }; + + fu::invoke_with_tuple(lam, std::move(myargs)); + + fu::sequence_generator<2>::type seqtype; + fu::sequence_generator<1>::type zero_seqtype; + std::cout << "ok" << std::endl; return 0; }