1 /*! 2 @file 3 Defines `boost::hana::on`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_FUNCTIONAL_ON_HPP 11 #define BOOST_HANA_FUNCTIONAL_ON_HPP 12 13 #include <boost/hana/config.hpp> 14 #include <boost/hana/detail/create.hpp> 15 #include <boost/hana/functional/infix.hpp> 16 17 #include <utility> 18 19 20 BOOST_HANA_NAMESPACE_BEGIN 21 //! @ingroup group-functional 22 //! Invoke a function with the result of invoking another function on 23 //! each argument. 24 //! 25 //! Specifically, `on(f, g)` is a function such that 26 //! @code 27 //! on(f, g)(x...) == f(g(x)...) 28 //! @endcode 29 //! 30 //! For convenience, `on` also supports infix application as provided 31 //! by `infix`. 32 //! 33 //! 34 //! @note 35 //! `on` is associative, i.e. `on(f, on(g, h))` is equivalent to 36 //! `on(on(f, g), h)`. 37 //! 38 //! @internal 39 //! ### Proof of associativity 40 //! 41 //! @code 42 //! on(f, on(g, h))(xs...) == f(on(g, h)(xs)...) 43 //! == f(g(h(xs))...) 44 //! 45 //! on(on(f, g), h)(xs...) == on(f, g)(h(xs)...) 46 //! == f(g(h(xs))...) 47 //! @endcode 48 //! @endinternal 49 //! 50 //! 51 //! ### Example 52 //! @include example/functional/on.cpp 53 #ifdef BOOST_HANA_DOXYGEN_INVOKED __anon980a07fd0102(auto&& f, auto&& g) 54 constexpr auto on = infix([](auto&& f, auto&& g) { 55 return [perfect-capture](auto&& ...x) -> decltype(auto) { 56 return forwarded(f)(g(forwarded(x))...); 57 }; 58 }); 59 #else 60 template <typename F, typename G> 61 struct on_t { 62 F f; G g; 63 template <typename ...X> 64 constexpr decltype(auto) operator()(X&& ...x) const& { 65 return f(g(static_cast<X&&>(x))...); 66 } 67 68 template <typename ...X> 69 constexpr decltype(auto) operator()(X&& ...x) & { 70 return f(g(static_cast<X&&>(x))...); 71 } 72 73 template <typename ...X> 74 constexpr decltype(auto) operator()(X&& ...x) && { 75 return std::move(f)(g(static_cast<X&&>(x))...); 76 } 77 }; 78 79 constexpr auto on = infix(detail::create<on_t>{}); 80 #endif 81 BOOST_HANA_NAMESPACE_END 82 83 #endif // !BOOST_HANA_FUNCTIONAL_ON_HPP 84