ecency-mobile/ios/Pods/boost-for-react-native/boost/hana/functional/compose.hpp

109 lines
3.4 KiB
C++

/*!
@file
Defines `boost::hana::compose`.
@copyright Louis Dionne 2013-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
#define BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <boost/hana/detail/variadic/foldl1.hpp>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @ingroup group-functional
//! Return the composition of two functions or more.
//!
//! `compose` is defined inductively. When given more than two functions,
//! `compose(f, g, h...)` is equivalent to `compose(f, compose(g, h...))`.
//! When given two functions, `compose(f, g)` is a function such that
//! @code
//! compose(f, g)(x, y...) == f(g(x), y...)
//! @endcode
//!
//! If you need composition of the form `f(g(x, y...))`, use `demux` instead.
//!
//! @note
//! `compose` is an associative operation; `compose(f, compose(g, h))`
//! is equivalent to `compose(compose(f, g), h)`.
//!
//! @internal
//! ### Proof of associativity
//!
//! @code
//! compose(f, compose(g, h))(x, xs...) == f(compose(g, h)(x), xs...)
//! == f(g(h(x)), xs...)
//!
//! compose(compose(f, g), h)(x, xs...) == compose(f, g)(h(x), xs...)
//! == f(g(h(x)), xs...)
//! @endcode
//! @endinternal
//!
//! ### Example
//! @include example/functional/compose.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto compose = [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& x, auto&& ...xs) -> decltype(auto) {
return forwarded(f1)(
forwarded(f2)(
...
forwarded(fn)(forwarded(x))
),
forwarded(xs)...
);
}
};
#else
template <typename F, typename G>
struct _compose {
F f; G g;
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) const& {
return f(
g(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) & {
return f(
g(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) && {
return std::move(f)(
std::move(g)(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
};
struct _make_compose {
template <typename F, typename G, typename ...H>
constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
return detail::variadic::foldl1(detail::create<_compose>{},
static_cast<F&&>(f),
static_cast<G&&>(g),
static_cast<H&&>(h)...
);
}
};
constexpr _make_compose compose{};
#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FUNCTIONAL_COMPOSE_HPP