Implement sequences and function invocation from tuples

This commit is contained in:
Denis Blank 2015-07-02 00:01:36 +02:00 committed by Naios
parent 44e96ac52b
commit 959bc87d00
2 changed files with 116 additions and 6 deletions

View File

@ -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<typename... Args>
struct identity { };
/// Sequence class which is used to carry parameter packs of unsigned integers.
template<size_t...>
struct sequence { };
/// The Sequence generator generates a sequence of numbers with the given size.
template<size_t...>
struct sequence_generator;
template<size_t... Stack>
struct sequence_generator<0, Stack...>
{
typedef sequence<Stack...> type;
};
template<size_t Position, size_t... Stack>
struct sequence_generator<Position, Stack...>
: public sequence_generator<Position - 1, Position - 1, Stack...> { };
/// Sequence generator alias
template<size_t Size>
using sequence_of_t = typename sequence_generator<Size>::type;
namespace detail
{
template<typename Function>
@ -55,6 +77,11 @@ namespace fu
typedef _RTy(*function_ptr)(_ATy...);
};
/// Pack in fu::identity
template<typename _RTy, typename... _ATy>
struct unwrap_function_impl<identity<_RTy, _ATy...>>
: unwrap_function_impl<_RTy(_ATy...)> { };
/// STL: std::function
template<typename _RTy, typename... _ATy>
struct unwrap_function_impl<std::function<_RTy(_ATy...)>>
@ -85,11 +112,6 @@ namespace fu
struct unwrap_function_impl<_RTy(_CTy::*)(_ATy...)>
: unwrap_function_impl<_RTy(_ATy...)> { };
/// Pack in fu::identity
template<typename _RTy, typename... _ATy>
struct unwrap_function_impl<identity<_RTy, _ATy...>>
: unwrap_function_impl<_RTy(_ATy...)> { };
/// Unwrap through pointer of functor.
template<typename Function>
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<typename Sequence>
struct invoker;
template<size_t... Sequence>
struct invoker<sequence<Sequence...>>
{
template<typename _FTy, typename _TTy>
static auto invoke(_FTy&& functional, _TTy&& tuple)
-> ::fu::return_type_of_t<typename std::decay<_FTy>::type>
{
return std::forward<_FTy>(functional)(std::get<Sequence>(std::forward<_TTy>(tuple))...);
}
};
}
/// Invokes a function type with the given tuple arguments.
template<typename _FTy, typename _TTy>
inline auto invoke_with_tuple(_FTy&& functional, _TTy&& tuple)
-> return_type_of_t<typename std::decay<_FTy>::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_

View File

@ -82,6 +82,8 @@ Continuable<std::unique_ptr<int>&&> MoveTest()
});
}
typedef std::unique_ptr<int> Moveable;
void testMoveAbleNormal(std::function<void(std::unique_ptr<int>&&)> callback)
{
std::unique_ptr<int> ptr(new int(5));
@ -93,6 +95,43 @@ void test_unwrap(std::string const& msg)
{
std::cout << msg << " is unwrappable: " << (fu::is_unwrappable<T...>::value ? "true" : "false") << std::endl;
}
/*
template<size_t N>
struct Apply {
template<typename F, typename T, typename... A>
static inline auto apply(F && f, T && t, A &&... a)
-> decltype(Apply<N-1>::apply(
::std::forward<F>(f), ::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
))
{
return Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
);
}
};
template<>
struct Apply<0> {
template<typename F, typename T, typename... A>
static inline auto apply(F && f, T &&, A &&... a)
-> decltype(::std::forward<F>(f)(::std::forward<A>(a)...))
{
return ::std::forward<F>(f)(::std::forward<A>(a)...);
}
};
template<typename F, typename T>
inline auto apply(F && f, T && t)
-> decltype(Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t)))
{
return Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t));
}
*/
int main(int /*argc*/, char** /*argv*/)
{
@ -281,6 +320,23 @@ int main(int /*argc*/, char** /*argv*/)
std::tuple<int, std::vector<int>> tup;
Moveable moveable(new int(7));
auto myargs = std::make_tuple(7, std::vector<int>({ 1, 2, 3 }), std::move(moveable));
std::function<int(int, std::vector<int>, Moveable&&)> lam = [](int given_i, std::vector<int> 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;
}