From 8632c41bd636db6abc2604a7fbe90fe285f6f248 Mon Sep 17 00:00:00 2001 From: Scott Prager Date: Thu, 26 Feb 2015 09:56:04 -0500 Subject: [PATCH] multary: implement as a partial function Not even multary needs to own the function it operates os. However, gcc seems unable to realize this in constexpr's possibly due to this: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55993 --- include/fu/basic.h | 57 ++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/include/fu/basic.h b/include/fu/basic.h index 3859ff4..4f5f6ed 100644 --- a/include/fu/basic.h +++ b/include/fu/basic.h @@ -188,40 +188,36 @@ constexpr auto part = ForwardT{}; /// A function that takes `n` or more arguments. If given only one argument, it /// will return a partial application. -template -struct multary_n_f : ToFunctor<_F> { - using F = ToFunctor<_F>; - - constexpr multary_n_f(F f) : F(std::move(f)) { } - +template +struct multary_n_f { // The result of applying this m arguments where m <= n. - template - using Partial = multary_n_f>; + template + using Partial = Part, Part>; /// Too few arguments: Return another multary function. - template> - constexpr Partial operator() (X...x) const & { - return Partial(closure(F(*this), std::move(x)...)); + template> + constexpr auto operator() (F f, X...x) const { + return part(multary_n_f{}, + closure(std::move(f), std::move(x)...)); } /// Exactly n arguments: Partially apply. - template> - constexpr Part operator() (X...x) const & { - return closure(F(*this), std::move(x)...); + template> + constexpr auto operator() (F&& f, X...x) const { + return closure(std::forward(f), std::move(x)...); } /// More than n arguments: invoke. - template n)>> - constexpr decltype(auto) operator() (X&&...x) const & + template n)>> + constexpr decltype(auto) operator() (F&& f, X&&...x) const { - return static_cast(*this)(std::forward(x)...); + return fu::invoke(std::forward(f), std::forward(x)...); } }; -template -struct multary_n_f<0, F> : ToFunctor { - using Fn = ToFunctor; - using Fn::operator(); +template<> +struct multary_n_f<0> : invoke_f { + using invoke_f::operator(); }; /// A function that takes two or more arguments. If given only one argument, it @@ -231,8 +227,8 @@ constexpr struct multary_f { // basic_multary = MakeT{}; // multary = part(basic_multary, Int<0>{}) template - constexpr multary_n_f<1, F> operator() (F f) const { - return multary_n_f<1, F>(std::move(f)); + constexpr auto operator() (F f) const { + return closure(multary_n_f<1>{}, std::move(f)); } } multary{}; @@ -244,16 +240,13 @@ constexpr struct multary_f { template struct make_multary_n_f { template - constexpr auto operator() (F f) const -> multary_n_f - { - return {std::move(f)}; + constexpr auto operator() (F f) const { + return closure(multary_n_f{}, std::move(f)); } template - constexpr auto operator() (std::reference_wrapper f) const - -> multary_n_f - { - return {std::move(f)}; + constexpr auto operator() (std::reference_wrapper f) const { + return part(multary_n_f{}, f.get()); } }; @@ -261,8 +254,8 @@ template constexpr auto multary_n = make_multary_n_f{}; #else template -constexpr multary_n_f multary_n(F f) { - return multary_n_f(std::move(f)); +constexpr auto multary_n(F f) { + return closure(multary_n_f{}, std::move(f)); } #endif // __clang__