Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:58

0001 /*!
0002 @file
0003 Defines `boost::hana::compose`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
0011 #define BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 #include <boost/hana/detail/create.hpp>
0015 #include <boost/hana/detail/variadic/foldl1.hpp>
0016 
0017 #include <utility>
0018 
0019 
0020 namespace boost { namespace hana {
0021     //! @ingroup group-functional
0022     //! Return the composition of two functions or more.
0023     //!
0024     //! `compose` is defined inductively. When given more than two functions,
0025     //! `compose(f, g, h...)` is equivalent to `compose(f, compose(g, h...))`.
0026     //! When given two functions, `compose(f, g)` is a function such that
0027     //! @code
0028     //!     compose(f, g)(x, y...) == f(g(x), y...)
0029     //! @endcode
0030     //!
0031     //! If you need composition of the form `f(g(x, y...))`, use `demux` instead.
0032     //!
0033     //! @note
0034     //! `compose` is an associative operation; `compose(f, compose(g, h))`
0035     //! is equivalent to `compose(compose(f, g), h)`.
0036     //!
0037     //! @internal
0038     //! ### Proof of associativity
0039     //!
0040     //! @code
0041     //!     compose(f, compose(g, h))(x, xs...) == f(compose(g, h)(x), xs...)
0042     //!                                         == f(g(h(x)), xs...)
0043     //!
0044     //!     compose(compose(f, g), h)(x, xs...) == compose(f, g)(h(x), xs...)
0045     //!                                         == f(g(h(x)), xs...)
0046     //! @endcode
0047     //! @endinternal
0048     //!
0049     //! ### Example
0050     //! @include example/functional/compose.cpp
0051 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0052     constexpr auto compose = [](auto&& f1, auto&& f2, ..., auto&& fn) {
0053         return [perfect-capture](auto&& x, auto&& ...xs) -> decltype(auto) {
0054             return forwarded(f1)(
0055                     forwarded(f2)(
0056                      ...
0057                       forwarded(fn)(forwarded(x))
0058                     ),
0059                     forwarded(xs)...
0060                 );
0061         }
0062     };
0063 #else
0064     template <typename F, typename G>
0065     struct _compose {
0066         F f; G g;
0067 
0068         template <typename X, typename ...Xs>
0069         constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) const& {
0070             return f(
0071                 g(static_cast<X&&>(x)),
0072                 static_cast<Xs&&>(xs)...
0073             );
0074         }
0075 
0076         template <typename X, typename ...Xs>
0077         constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) & {
0078             return f(
0079                 g(static_cast<X&&>(x)),
0080                 static_cast<Xs&&>(xs)...
0081             );
0082         }
0083 
0084         template <typename X, typename ...Xs>
0085         constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) && {
0086             return std::move(f)(
0087                 std::move(g)(static_cast<X&&>(x)),
0088                 static_cast<Xs&&>(xs)...
0089             );
0090         }
0091     };
0092 
0093     struct _make_compose {
0094         template <typename F, typename G, typename ...H>
0095         constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
0096             return detail::variadic::foldl1(detail::create<_compose>{},
0097                 static_cast<F&&>(f),
0098                 static_cast<G&&>(g),
0099                 static_cast<H&&>(h)...
0100             );
0101         }
0102     };
0103 
0104     BOOST_HANA_INLINE_VARIABLE constexpr _make_compose compose{};
0105 #endif
0106 }} // end namespace boost::hana
0107 
0108 #endif // !BOOST_HANA_FUNCTIONAL_COMPOSE_HPP