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

202 lines
6.3 KiB
C++

/*!
@file
Defines `boost::hana::iterate`.
@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_ITERATE_HPP
#define BOOST_HANA_FUNCTIONAL_ITERATE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/functional/partial.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN
//! @ingroup group-functional
//! Applies another function `n` times to its argument.
//!
//! Given a function `f` and an argument `x`, `iterate<n>(f, x)` returns
//! the result of applying `f` `n` times to its argument. In other words,
//! @code
//! iterate<n>(f, x) == f(f( ... f(x)))
//! ^^^^^^^^^^ n times total
//! @endcode
//!
//! If `n == 0`, `iterate<n>(f, x)` returns the `x` argument unchanged
//! and `f` is never applied. It is important to note that the function
//! passed to `iterate<n>` must be a unary function. Indeed, since `f`
//! will be called with the result of the previous `f` application, it
//! may only take a single argument.
//!
//! In addition to what's documented above, `iterate` can also be
//! partially applied to the function argument out-of-the-box. In
//! other words, `iterate<n>(f)` is a function object applying `f`
//! `n` times to the argument it is called with, which means that
//! @code
//! iterate<n>(f)(x) == iterate<n>(f, x)
//! @endcode
//!
//! This is provided for convenience, and it turns out to be especially
//! useful in conjunction with higher-order algorithms.
//!
//!
//! Signature
//! ---------
//! Given a function \f$ f : T \to T \f$ and `x` and argument of data
//! type `T`, the signature is
//! \f$
//! \mathtt{iterate_n} : (T \to T) \times T \to T
//! \f$
//!
//! @tparam n
//! An unsigned integer representing the number of times that `f`
//! should be applied to its argument.
//!
//! @param f
//! A function to apply `n` times to its argument.
//!
//! @param x
//! The initial value to call `f` with.
//!
//!
//! Example
//! -------
//! @include example/functional/iterate.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <std::size_t n>
constexpr auto iterate = [](auto&& f) {
return [perfect-capture](auto&& x) -> decltype(auto) {
return f(f( ... f(forwarded(x))));
};
};
#else
template <std::size_t n, typename = when<true>>
struct iterate_t;
template <>
struct iterate_t<0> {
template <typename F, typename X>
constexpr X operator()(F&&, X&& x) const
{ return static_cast<X&&>(x); }
};
template <>
struct iterate_t<1> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(static_cast<X&&>(x));
}
};
template <>
struct iterate_t<2> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(static_cast<X&&>(x)));
}
};
template <>
struct iterate_t<3> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(static_cast<X&&>(x))));
}
};
template <>
struct iterate_t<4> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(f(static_cast<X&&>(x)))));
}
};
template <>
struct iterate_t<5> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(f(f(static_cast<X&&>(x))))));
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 6) && (n < 12)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 6>{}(f,
f(f(f(f(f(f(static_cast<X&&>(x)))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 12) && (n < 24)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 12>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 24) && (n < 48)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 24>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
))))))))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 48)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 48>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
))))))))))))
))))))))))))
))))))))))))
);
}
};
template <std::size_t n>
struct make_iterate_t {
template <typename F>
constexpr decltype(auto) operator()(F&& f) const
{ return hana::partial(iterate_t<n>{}, static_cast<F&&>(f)); }
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n>{}(static_cast<F&&>(f),
static_cast<X&&>(x));
}
};
template <std::size_t n>
constexpr make_iterate_t<n> iterate{};
#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_FUNCTIONAL_ITERATE_HPP