22 #ifndef GEARS_FUNCTIONAL_CURRY_HPP
23 #define GEARS_FUNCTIONAL_CURRY_HPP
25 #include "../adl/get.hpp"
26 #include "../meta/indices.hpp"
27 #include "../meta/meta.hpp"
30 namespace functional {
32 template<
typename Tuple>
33 using IndicesFor = meta::build_indices<std::tuple_size<Tuple>::value>;
35 template<
typename F,
typename Tuple,
size_t... Indices,
36 typename Return = decltype(std::declval<F>()(adl::get<Indices>(std::declval<Tuple>())...))>
37 constexpr Return invoke_impl(F&& f, Tuple&& t, meta::indices<Indices...>) {
38 return std::forward<F>(f)(adl::get<Indices>(std::forward<Tuple>(t))...);
41 template<
typename F,
typename Tuple,
42 typename Return = decltype(invoke_impl(std::declval<F>(), std::declval<Tuple>(), IndicesFor<Tuple>{}))>
43 constexpr Return invoke_tup(F&& f, Tuple&& tuple) {
44 return invoke_impl(std::forward<F>(f), std::forward<Tuple>(tuple), IndicesFor<Tuple>{});
47 struct is_reference_wrapper_impl {
48 template<
typename T,
typename U =
typename T::type>
49 static auto test(
int) -> decltype(std::declval<T&>().
get(), std::is_convertible<T, U&>{}) {}
51 static std::false_type test(...);
55 struct is_reference_wrapper : decltype(is_reference_wrapper_impl::test<T>(0)) {};
59 using type =
typename T::type&;
63 struct special_decay {
64 using type = meta::TypeIf<is_reference_wrapper<T>, unref<T>, meta::identity<T>>;
68 using SpecialDecay = meta::Type<special_decay<meta::Decay<T>>>;
71 template<
typename Function,
typename... Args>
73 using tuple_type = std::tuple<Args...>;
78 constexpr curry_type(Function&& f, tuple_type n) noexcept: func(std::forward<Function>(f)), args(std::move(n)) {}
80 template<
typename... T>
81 constexpr
auto operator()(T&&... t) -> decltype(detail::invoke_tup(func, std::tuple_cat(std::move(args), std::make_tuple(t...)))) {
82 return detail::invoke_tup(func, std::tuple_cat(std::move(args), std::make_tuple(t...)));
115 template<
typename Function,
typename... Args>
116 constexpr curry_type<Function, detail::SpecialDecay<Args>...>
curry(Function&& f, Args&&... args) {
117 return { std::forward<Function>(f), std::make_tuple(args...) };
122 #endif // GEARS_FUNCTIONAL_CURRY_HPP