on.hpp 2.2 KB

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