summaryrefslogtreecommitdiff
path: root/boost/hana/functional
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/functional')
-rw-r--r--boost/hana/functional/always.hpp64
-rw-r--r--boost/hana/functional/apply.hpp85
-rw-r--r--boost/hana/functional/arg.hpp141
-rw-r--r--boost/hana/functional/capture.hpp112
-rw-r--r--boost/hana/functional/compose.hpp108
-rw-r--r--boost/hana/functional/curry.hpp169
-rw-r--r--boost/hana/functional/demux.hpp269
-rw-r--r--boost/hana/functional/fix.hpp83
-rw-r--r--boost/hana/functional/flip.hpp73
-rw-r--r--boost/hana/functional/id.hpp38
-rw-r--r--boost/hana/functional/infix.hpp184
-rw-r--r--boost/hana/functional/iterate.hpp201
-rw-r--r--boost/hana/functional/lockstep.hpp114
-rw-r--r--boost/hana/functional/on.hpp83
-rw-r--r--boost/hana/functional/overload.hpp88
-rw-r--r--boost/hana/functional/overload_linearly.hpp105
-rw-r--r--boost/hana/functional/partial.hpp107
-rw-r--r--boost/hana/functional/placeholder.hpp263
-rw-r--r--boost/hana/functional/reverse_partial.hpp101
19 files changed, 2388 insertions, 0 deletions
diff --git a/boost/hana/functional/always.hpp b/boost/hana/functional/always.hpp
new file mode 100644
index 0000000000..249233d3f2
--- /dev/null
+++ b/boost/hana/functional/always.hpp
@@ -0,0 +1,64 @@
+/*!
+@file
+Defines `boost::hana::always`.
+
+@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_ALWAYS_HPP
+#define BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return a constant function returning `x` regardless of the
+ //! argument(s) it is invoked with.
+ //!
+ //! Specifically, `always(x)` is a function such that
+ //! @code
+ //! always(x)(y...) == x
+ //! @endcode
+ //! for any `y...`. A copy of `x` is made and it is owned by the
+ //! `always(x)` function. When `always(x)` is called, it will return
+ //! a reference to the `x` it owns. This reference is valid as long
+ //! as `always(x)` is in scope.
+ //!
+ //!
+ //! ### Example
+ //! @include example/functional/always.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto always = [](auto&& x) {
+ return [perfect-capture](auto const& ...y) -> decltype(auto) {
+ return forwarded(x);
+ };
+ };
+#else
+ template <typename T>
+ struct _always {
+ T val_;
+
+ template <typename ...Args>
+ constexpr T const& operator()(Args const& ...) const&
+ { return val_; }
+
+ template <typename ...Args>
+ constexpr T& operator()(Args const& ...) &
+ { return val_; }
+
+ template <typename ...Args>
+ constexpr T operator()(Args const& ...) &&
+ { return std::move(val_); }
+ };
+
+ constexpr detail::create<_always> always{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
diff --git a/boost/hana/functional/apply.hpp b/boost/hana/functional/apply.hpp
new file mode 100644
index 0000000000..75a7f9483d
--- /dev/null
+++ b/boost/hana/functional/apply.hpp
@@ -0,0 +1,85 @@
+/*!
+@file
+Defines `boost::hana::apply`.
+
+@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_APPLY_HPP
+#define BOOST_HANA_FUNCTIONAL_APPLY_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invokes a Callable with the given arguments.
+ //!
+ //! This is equivalent to [std::invoke][1] that will be added in C++17.
+ //! However, `apply` is a function object instead of a function, which
+ //! makes it possible to pass it to higher-order algorithms.
+ //!
+ //!
+ //! @param f
+ //! A [Callable][2] to be invoked with the given arguments.
+ //!
+ //! @param x...
+ //! The arguments to call `f` with. The number of `x...` must match the
+ //! arity of `f`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/apply.cpp
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/utility/functional/invoke
+ //! [2]: http://en.cppreference.com/w/cpp/concept/Callable
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto apply = [](auto&& f, auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(forwarded(x)...);
+ };
+#else
+ struct apply_t {
+ template <typename F, typename... Args>
+ constexpr auto operator()(F&& f, Args&&... args) const ->
+ decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...))
+ {
+ return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
+ }
+
+ template <typename Base, typename T, typename Derived>
+ constexpr auto operator()(T Base::*pmd, Derived&& ref) const ->
+ decltype(static_cast<Derived&&>(ref).*pmd)
+ {
+ return static_cast<Derived&&>(ref).*pmd;
+ }
+
+ template <typename PMD, typename Pointer>
+ constexpr auto operator()(PMD pmd, Pointer&& ptr) const ->
+ decltype((*static_cast<Pointer&&>(ptr)).*pmd)
+ {
+ return (*static_cast<Pointer&&>(ptr)).*pmd;
+ }
+
+ template <typename Base, typename T, typename Derived, typename... Args>
+ constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const ->
+ decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...))
+ {
+ return (static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...);
+ }
+
+ template <typename PMF, typename Pointer, typename... Args>
+ constexpr auto operator()(PMF pmf, Pointer&& ptr, Args&& ...args) const ->
+ decltype(((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...))
+ {
+ return ((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...);
+ }
+ };
+
+ constexpr apply_t apply{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_APPLY_HPP
diff --git a/boost/hana/functional/arg.hpp b/boost/hana/functional/arg.hpp
new file mode 100644
index 0000000000..c9c68f0eae
--- /dev/null
+++ b/boost/hana/functional/arg.hpp
@@ -0,0 +1,141 @@
+/*!
+@file
+Defines `boost::hana::arg`.
+
+@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_ARG_HPP
+#define BOOST_HANA_FUNCTIONAL_ARG_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <type_traits>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return the `n`th passed argument.
+ //!
+ //! Specifically, `arg<n>(x1, ..., xn, ..., xm)` is equivalent to `xn`.
+ //! Note that indexing starts at 1, so `arg<1>` returns the 1st argument,
+ //! `arg<2>` the 2nd and so on. Using `arg<0>` is an error. Passing
+ //! less than `n` arguments to `arg<n>` is also an error.
+ //!
+ //!
+ //! @tparam n
+ //! An unsigned integer representing the argument to return. `n` must be
+ //! positive (meaning nonzero).
+ //!
+ //! @param x1, ..., xm
+ //! A variadic pack of arguments from which the `n`th one is returned.
+ //!
+ //!
+ //! @internal
+ //! ### Discussion: could `n` be dynamic?
+ //! We could have chosen `arg` to be used like `arg(n)(x...)` instead of
+ //! `arg<n>(x...)`. Provided all the arguments were of the same type, it
+ //! would then be possible for `n` to only be known at runtime. However,
+ //! we would then lose the ability to assert the in-boundedness of `n`
+ //! statically.
+ //!
+ //! ### Rationale for `n` being a non-type template parameter
+ //! I claim that the only interesting use case is with a compile-time
+ //! `n`, which means that the usage would become `arg(int_<n>)(x...)`,
+ //! which is more cumbersome to write than `arg<n>(x...)`. This is open
+ //! for discussion.
+ //! @endinternal
+ //!
+ //! ### Example
+ //! @include example/functional/arg.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto arg = [](auto&& x1, ..., auto&& xm) -> decltype(auto) {
+ return forwarded(xn);
+ };
+#else
+ template <std::size_t n, typename = void>
+ struct arg_t;
+
+ template <>
+ struct arg_t<1> {
+ template <typename X1, typename ...Xn>
+ constexpr X1 operator()(X1&& x1, Xn&& ...) const
+ { return static_cast<X1&&>(x1); }
+ };
+
+ template <>
+ struct arg_t<2> {
+ template <typename X1, typename X2, typename ...Xn>
+ constexpr X2 operator()(X1&&, X2&& x2, Xn&& ...) const
+ { return static_cast<X2&&>(x2); }
+ };
+
+ template <>
+ struct arg_t<3> {
+ template <typename X1, typename X2, typename X3, typename ...Xn>
+ constexpr X3 operator()(X1&&, X2&&, X3&& x3, Xn&& ...) const
+ { return static_cast<X3&&>(x3); }
+ };
+
+ template <>
+ struct arg_t<4> {
+ template <typename X1, typename X2, typename X3, typename X4, typename ...Xn>
+ constexpr X4 operator()(X1&&, X2&&, X3&&, X4&& x4, Xn&& ...) const
+ { return static_cast<X4&&>(x4); }
+ };
+
+ template <>
+ struct arg_t<5> {
+ template <typename X1, typename X2, typename X3, typename X4,
+ typename X5, typename ...Xn>
+ constexpr X5 operator()(X1&&, X2&&, X3&&, X4&&, X5&& x5, Xn&& ...) const
+ { return static_cast<X5&&>(x5); }
+ };
+
+ template <std::size_t n, typename>
+ struct arg_t {
+ static_assert(n > 0,
+ "invalid usage of boost::hana::arg<n> with n == 0");
+
+ template <typename X1, typename X2, typename X3, typename X4,
+ typename X5, typename ...Xn>
+ constexpr decltype(auto)
+ operator()(X1&&, X2&&, X3&&, X4&&, X5&&, Xn&& ...xn) const {
+ static_assert(sizeof...(xn) >= n - 5,
+ "invalid usage of boost::hana::arg<n> with too few arguments");
+
+ // Since compilers will typically try to continue for a bit after
+ // an error/static assertion, we must avoid sending the compiler
+ // in a very long computation if n == 0.
+ return arg_t<n == 0 ? 1 : n - 5>{}(static_cast<Xn&&>(xn)...);
+ }
+ };
+
+ template <std::size_t n>
+ struct arg_t<n, std::enable_if_t<(n > 25)>> {
+ template <
+ typename X1, typename X2, typename X3, typename X4, typename X5,
+ typename X6, typename X7, typename X8, typename X9, typename X10,
+ typename X11, typename X12, typename X13, typename X14, typename X15,
+ typename X16, typename X17, typename X18, typename X19, typename X20,
+ typename X21, typename X22, typename X23, typename X24, typename X25,
+ typename ...Xn>
+ constexpr decltype(auto)
+ operator()(X1&&, X2&&, X3&&, X4&&, X5&&,
+ X6&&, X7&&, X8&&, X9&&, X10&&,
+ X11&&, X12&&, X13&&, X14&&, X15&&,
+ X16&&, X17&&, X18&&, X19&&, X20&&,
+ X21&&, X22&&, X23&&, X24&&, X25&&, Xn&& ...xn) const
+ { return arg_t<n - 25>{}(static_cast<Xn&&>(xn)...); }
+ };
+
+ template <std::size_t n>
+ constexpr arg_t<n> arg{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ARG_HPP
diff --git a/boost/hana/functional/capture.hpp b/boost/hana/functional/capture.hpp
new file mode 100644
index 0000000000..0b5a4677d8
--- /dev/null
+++ b/boost/hana/functional/capture.hpp
@@ -0,0 +1,112 @@
+/*!
+@file
+Defines `boost::hana::capture`.
+
+@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_CAPTURE_HPP
+#define BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Create a function capturing the given variables.
+ //!
+ //! Given 0 or more variables, `capture` creates a closure that can be
+ //! used to partially apply a function. This is very similar to `partial`,
+ //! except that `capture` allows the partially applied function to be
+ //! specified later. Specifically, `capture(vars...)` is a function object
+ //! taking a function `f` and returning `f` partially applied to `vars...`.
+ //! In other words,
+ //! @code
+ //! capture(vars...)(f)(args...) == f(vars..., args...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(vars) + sizeof...(args)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/capture.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto capture = [](auto&& ...variables) {
+ return [perfect-capture](auto&& f) {
+ return [perfect-capture](auto&& ...args) -> decltype(auto) {
+ return forwarded(f)(forwarded(variables)..., forwarded(args)...);
+ };
+ };
+ };
+#else
+ namespace detail {
+ template <typename F, typename Closure, std::size_t ...i>
+ constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence<i...>) {
+ return hana::partial(static_cast<F&&>(f),
+ hana::get_impl<i>(static_cast<Closure&&>(closure).storage_)...
+ );
+ }
+ }
+
+ template <typename ...X>
+ struct capture_t;
+
+ struct make_capture_t {
+ struct secret { };
+ template <typename ...X>
+ constexpr capture_t<typename detail::decay<X>::type...>
+ operator()(X&& ...x) const {
+ return {secret{}, static_cast<X&&>(x)...};
+ }
+ };
+
+ template <typename ...X>
+ struct capture_t {
+ template <typename ...Y>
+ constexpr capture_t(make_capture_t::secret, Y&& ...y)
+ : storage_{static_cast<Y&&>(y)...}
+ { }
+
+ basic_tuple<X...> storage_;
+
+ template <typename F>
+ constexpr auto operator()(F&& f) const& {
+ return detail::apply_capture(
+ static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+
+ template <typename F>
+ constexpr auto operator()(F&& f) & {
+ return detail::apply_capture(
+ static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+
+ template <typename F>
+ constexpr auto operator()(F&& f) && {
+ return detail::apply_capture(
+ static_cast<F&&>(f), static_cast<capture_t&&>(*this),
+ std::make_index_sequence<sizeof...(X)>{}
+ );
+ }
+ };
+
+ constexpr make_capture_t capture{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
diff --git a/boost/hana/functional/compose.hpp b/boost/hana/functional/compose.hpp
new file mode 100644
index 0000000000..3250cee4db
--- /dev/null
+++ b/boost/hana/functional/compose.hpp
@@ -0,0 +1,108 @@
+/*!
+@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
diff --git a/boost/hana/functional/curry.hpp b/boost/hana/functional/curry.hpp
new file mode 100644
index 0000000000..23b3694b8c
--- /dev/null
+++ b/boost/hana/functional/curry.hpp
@@ -0,0 +1,169 @@
+/*!
+@file
+Defines `boost::hana::curry`.
+
+@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_CURRY_HPP
+#define BOOST_HANA_FUNCTIONAL_CURRY_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/apply.hpp>
+#include <boost/hana/functional/partial.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Curry a function up to the given number of arguments.
+ //!
+ //! [Currying][Wikipedia.currying] is a technique in which we consider a
+ //! function taking multiple arguments (or, equivalently, a tuple of
+ //! arguments), and turn it into a function which takes a single argument
+ //! and returns a function to handle the remaining arguments. To help
+ //! visualize, let's denote the type of a function `f` which takes
+ //! arguments of types `X1, ..., Xn` and returns a `R` as
+ //! @code
+ //! (X1, ..., Xn) -> R
+ //! @endcode
+ //!
+ //! Then, currying is the process of taking `f` and turning it into an
+ //! equivalent function (call it `g`) of type
+ //! @code
+ //! X1 -> (X2 -> (... -> (Xn -> R)))
+ //! @endcode
+ //!
+ //! This gives us the following equivalence, where `x1`, ..., `xn` are
+ //! objects of type `X1`, ..., `Xn` respectively:
+ //! @code
+ //! f(x1, ..., xn) == g(x1)...(xn)
+ //! @endcode
+ //!
+ //! Currying can be useful in several situations, especially when working
+ //! with higher-order functions.
+ //!
+ //! This `curry` utility is an implementation of currying in C++.
+ //! Specifically, `curry<n>(f)` is a function such that
+ //! @code
+ //! curry<n>(f)(x1)...(xn) == f(x1, ..., xn)
+ //! @endcode
+ //!
+ //! Note that the `n` has to be specified explicitly because the existence
+ //! of functions with variadic arguments in C++ make it impossible to know
+ //! when currying should stop.
+ //!
+ //! Unlike usual currying, this implementation also allows a curried
+ //! function to be called with several arguments at a time. Hence, the
+ //! following always holds
+ //! @code
+ //! curry<n>(f)(x1, ..., xk) == curry<n - k>(f)(x1)...(xk)
+ //! @endcode
+ //!
+ //! Of course, this requires `k` to be less than or equal to `n`; failure
+ //! to satisfy this will trigger a static assertion. This syntax is
+ //! supported because it makes curried functions usable where normal
+ //! functions are expected.
+ //!
+ //! Another "extension" is that `curry<0>(f)` is supported: `curry<0>(f)`
+ //! is a nullary function; whereas the classical definition for currying
+ //! seems to leave this case undefined, as nullary functions don't make
+ //! much sense in purely functional languages.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/curry.cpp
+ //!
+ //!
+ //! [Wikipedia.currying]: http://en.wikipedia.org/wiki/Currying
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ template <std::size_t n>
+ constexpr auto curry = [](auto&& f) {
+ return [perfect-capture](auto&& x1) {
+ return [perfect-capture](auto&& x2) {
+ ...
+ return [perfect-capture](auto&& xn) -> decltype(auto) {
+ return forwarded(f)(
+ forwarded(x1), forwarded(x2), ..., forwarded(xn)
+ );
+ };
+ };
+ };
+ };
+#else
+ template <std::size_t n, typename F>
+ struct curry_t;
+
+ template <std::size_t n>
+ struct make_curry_t {
+ template <typename F>
+ constexpr curry_t<n, typename std::decay<F>::type>
+ operator()(F&& f) const { return {static_cast<F&&>(f)}; }
+ };
+
+ template <std::size_t n>
+ constexpr make_curry_t<n> curry{};
+
+ namespace curry_detail {
+ template <std::size_t n>
+ constexpr make_curry_t<n> curry_or_call{};
+
+ template <>
+ constexpr auto curry_or_call<0> = apply;
+ }
+
+ template <std::size_t n, typename F>
+ struct curry_t {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(f, static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(f, static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ static_assert(sizeof...(x) <= n,
+ "too many arguments provided to boost::hana::curry");
+ return curry_detail::curry_or_call<n - sizeof...(x)>(
+ partial(std::move(f), static_cast<X&&>(x)...)
+ );
+ }
+ };
+
+ template <typename F>
+ struct curry_t<0, F> {
+ F f;
+
+ constexpr decltype(auto) operator()() const&
+ { return f(); }
+
+ constexpr decltype(auto) operator()() &
+ { return f(); }
+
+ constexpr decltype(auto) operator()() &&
+ { return std::move(f)(); }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_CURRY_HPP
diff --git a/boost/hana/functional/demux.hpp b/boost/hana/functional/demux.hpp
new file mode 100644
index 0000000000..c1ed03634e
--- /dev/null
+++ b/boost/hana/functional/demux.hpp
@@ -0,0 +1,269 @@
+/*!
+@file
+Defines `boost::hana::demux`.
+
+@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_DEMUX_HPP
+#define BOOST_HANA_FUNCTIONAL_DEMUX_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the results of invoking other functions
+ //! on its arguments.
+ //!
+ //! Specifically, `demux(f)(g...)` is a function such that
+ //! @code
+ //! demux(f)(g...)(x...) == f(g(x...)...)
+ //! @endcode
+ //!
+ //! Each `g` is called with all the arguments, and then `f` is called
+ //! with the result of each `g`. Hence, the arity of `f` must match
+ //! the number of `g`s.
+ //!
+ //! This is called `demux` because of a vague similarity between this
+ //! device and a demultiplexer in signal processing. `demux` takes what
+ //! can be seen as a continuation (`f`), a bunch of functions to split a
+ //! signal (`g...`) and zero or more arguments representing the signal
+ //! (`x...`). Then, it calls the continuation with the result of
+ //! splitting the signal with whatever functions where given.
+ //!
+ //! @note
+ //! When used with two functions only, `demux` is associative. In other
+ //! words (and noting `demux(f, g) = demux(f)(g)` to ease the notation),
+ //! it is true that `demux(demux(f, g), h) == demux(f, demux(g, h))`.
+ //!
+ //!
+ //! Signature
+ //! ---------
+ //! The signature of `demux` is
+ //! \f[
+ //! \mathtt{demux} :
+ //! (B_1 \times \dotsb \times B_n \to C)
+ //! \to ((A_1 \times \dotsb \times A_n \to B_1)
+ //! \times \dotsb
+ //! \times (A_1 \times \dotsb \times A_n \to B_n))
+ //! \to (A_1 \times \dotsb \times A_n \to C)
+ //! \f]
+ //!
+ //! This can be rewritten more tersely as
+ //! \f[
+ //! \mathtt{demux} :
+ //! \left(\prod_{i=1}^n B_i \to C \right)
+ //! \to \prod_{j=1}^n \left(\prod_{i=1}^n A_i \to B_j \right)
+ //! \to \left(\prod_{i=1}^n A_i \to C \right)
+ //! \f]
+ //!
+ //!
+ //! Link with normal composition
+ //! ----------------------------
+ //! The signature of `compose` is
+ //! \f[
+ //! \mathtt{compose} : (B \to C) \times (A \to B) \to (A \to C)
+ //! \f]
+ //!
+ //! A valid observation is that this coincides exactly with the type
+ //! of `demux` when used with a single unary function. Actually, both
+ //! functions are equivalent:
+ //! @code
+ //! demux(f)(g)(x) == compose(f, g)(x)
+ //! @endcode
+ //!
+ //! However, let's now consider the curried version of `compose`,
+ //! `curry<2>(compose)`:
+ //! \f[
+ //! \mathtt{curry_2(compose)} : (B \to C) \to ((A \to B) \to (A \to C))
+ //! \f]
+ //!
+ //! For the rest of this explanation, we'll just consider the curried
+ //! version of `compose` and so we'll use `compose` instead of
+ //! `curry<2>(compose)` to lighten the notation. With currying, we can
+ //! now consider `compose` applied to itself:
+ //! \f[
+ //! \mathtt{compose(compose, compose)} :
+ //! (B \to C) \to (A_1 \to A_2 \to B) \to (A_1 \to A_2 \to C)
+ //! \f]
+ //!
+ //! If we uncurry deeply the above expression, we obtain
+ //! \f[
+ //! \mathtt{compose(compose, compose)} :
+ //! (B \to C) \times (A_1 \times A_2 \to B) \to (A_1 \times A_2 \to C)
+ //! \f]
+ //!
+ //! This signature is exactly the same as that of `demux` when given a
+ //! single binary function, and indeed they are equivalent definitions.
+ //! We can also generalize this further by considering
+ //! `compose(compose(compose, compose), compose)`:
+ //! \f[
+ //! \mathtt{compose(compose(compose, compose), compose)} :
+ //! (B \to C) \to (A_1 \to A_2 \to A_3 \to B)
+ //! \to (A_1 \to A_2 \to A_3 \to C)
+ //! \f]
+ //!
+ //! which uncurries to
+ //! \f[
+ //! \mathtt{compose(compose(compose, compose), compose)} :
+ //! (B \to C) \times (A_1 \times A_2 \times A_3 \to B)
+ //! \to (A_1 \times A_2 \times A_3 \to C)
+ //! \f]
+ //!
+ //! This signature is exactly the same as that of `demux` when given a
+ //! single ternary function. Hence, for a single n-ary function `g`,
+ //! `demux(f)(g)` is equivalent to the n-times composition of `compose`
+ //! with itself, applied to `g` and `f`:
+ //! @code
+ //! demux(f)(g) == fold_left([compose, ..., compose], id, compose)(g, f)
+ //! // ^^^^^^^^^^^^^^^^^^^^^ n times
+ //! @endcode
+ //!
+ //! More information on this insight can be seen [here][1]. Also, I'm
+ //! not sure how this insight could be generalized to more than one
+ //! function `g`, or if that is even possible.
+ //!
+ //!
+ //! Proof of associativity in the binary case
+ //! -----------------------------------------
+ //! As explained above, `demux` is associative when it is used with
+ //! two functions only. Indeed, given functions `f`, `g` and `h` with
+ //! suitable signatures, we have
+ //! @code
+ //! demux(f)(demux(g)(h))(x...) == f(demux(g)(h)(x...))
+ //! == f(g(h(x...)))
+ //! @endcode
+ //!
+ //! On the other hand, we have
+ //! @code
+ //! demux(demux(f)(g))(h)(x...) == demux(f)(g)(h(x...))
+ //! == f(g(h(x...)))
+ //! @endcode
+ //!
+ //! and hence `demux` is associative in the binary case.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/demux.cpp
+ //!
+ //! [1]: http://stackoverflow.com/q/5821089/627587
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto demux = [](auto&& f) {
+ return [perfect-capture](auto&& ...g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ // x... can't be forwarded unless there is a single g
+ // function, or that could cause double-moves.
+ return forwarded(f)(forwarded(g)(x...)...);
+ };
+ };
+ };
+#else
+ template <typename F>
+ struct pre_demux_t;
+
+ struct make_pre_demux_t {
+ struct secret { };
+ template <typename F>
+ constexpr pre_demux_t<typename detail::decay<F>::type> operator()(F&& f) const {
+ return {static_cast<F&&>(f)};
+ }
+ };
+
+ template <typename Indices, typename F, typename ...G>
+ struct demux_t;
+
+ template <typename F>
+ struct pre_demux_t {
+ F f;
+
+ template <typename ...G>
+ constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename detail::decay<G>::type...>
+ operator()(G&& ...g) const& {
+ return {make_pre_demux_t::secret{}, this->f, static_cast<G&&>(g)...};
+ }
+
+ template <typename ...G>
+ constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename detail::decay<G>::type...>
+ operator()(G&& ...g) && {
+ return {make_pre_demux_t::secret{}, static_cast<F&&>(this->f), static_cast<G&&>(g)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...G>
+ struct demux_t<std::index_sequence<n...>, F, G...> {
+ template <typename ...T>
+ constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G...> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(x...)...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(x...)...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<n+1>(storage_))(x...)...
+ );
+ }
+ };
+
+ template <typename F, typename G>
+ struct demux_t<std::index_sequence<0>, F, G> {
+ template <typename ...T>
+ constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<1>(storage_)(static_cast<X&&>(x)...)
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<1>(storage_))(static_cast<X&&>(x)...)
+ );
+ }
+ };
+
+ constexpr make_pre_demux_t demux{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_DEMUX_HPP
diff --git a/boost/hana/functional/fix.hpp b/boost/hana/functional/fix.hpp
new file mode 100644
index 0000000000..007ecba1a1
--- /dev/null
+++ b/boost/hana/functional/fix.hpp
@@ -0,0 +1,83 @@
+/*!
+@file
+Defines `boost::hana::fix`.
+
+@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_FIX_HPP
+#define BOOST_HANA_FUNCTIONAL_FIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return a function computing the fixed point of a function.
+ //!
+ //! `fix` is an implementation of the [Y-combinator][], also called the
+ //! fixed-point combinator. It encodes the idea of recursion, and in fact
+ //! any recursive function can be written in terms of it.
+ //!
+ //! Specifically, `fix(f)` is a function such that
+ //! @code
+ //! fix(f)(x...) == f(fix(f), x...)
+ //! @endcode
+ //!
+ //! This definition allows `f` to use its first argument as a continuation
+ //! to call itself recursively. Indeed, if `f` calls its first argument
+ //! with `y...`, it is equivalent to calling `f(fix(f), y...)` per the
+ //! above equation.
+ //!
+ //! Most of the time, it is more convenient and efficient to define
+ //! recursive functions without using a fixed-point combinator. However,
+ //! there are some cases where `fix` provides either more flexibility
+ //! (e.g. the ability to change the callback inside `f`) or makes it
+ //! possible to write functions that couldn't be defined recursively
+ //! otherwise.
+ //!
+ //! @param f
+ //! A function called as `f(self, x...)`, where `x...` are the arguments
+ //! in the `fix(f)(x...)` expression and `self` is `fix(f)`.
+ //!
+ //! ### Example
+ //! @include example/functional/fix.cpp
+ //!
+ //! [Y-combinator]: http://en.wikipedia.org/wiki/Fixed-point_combinator
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto fix = [](auto&& f) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(fix(f), forwarded(x)...);
+ };
+ };
+#else
+ template <typename F>
+ struct fix_t;
+
+ constexpr detail::create<fix_t> fix{};
+
+ template <typename F>
+ struct fix_t {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const&
+ { return f(fix(f), static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &
+ { return f(fix(f), static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &&
+ { return std::move(f)(fix(f), static_cast<X&&>(x)...); }
+ };
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_FIX_HPP
diff --git a/boost/hana/functional/flip.hpp b/boost/hana/functional/flip.hpp
new file mode 100644
index 0000000000..3da81eddd7
--- /dev/null
+++ b/boost/hana/functional/flip.hpp
@@ -0,0 +1,73 @@
+/*!
+@file
+Defines `boost::hana::flip`.
+
+@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_FLIP_HPP
+#define BOOST_HANA_FUNCTIONAL_FLIP_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with its two first arguments reversed.
+ //!
+ //! Specifically, `flip(f)` is a function such that
+ //! @code
+ //! flip(f)(x, y, z...) == f(y, x, z...)
+ //! @endcode
+ //!
+ //! ### Example
+ //! @include example/functional/flip.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto flip = [](auto&& f) {
+ return [perfect-capture](auto&& x, auto&& y, auto&& ...z) -> decltype(auto) {
+ return forwarded(f)(forwarded(y), forwarded(x), forwarded(z)...);
+ };
+ };
+#else
+ template <typename F>
+ struct flip_t {
+ F f;
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) const& {
+ return f(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) & {
+ return f(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+
+ template <typename X, typename Y, typename ...Z>
+ constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) && {
+ return std::move(f)(
+ static_cast<Y&&>(y),
+ static_cast<X&&>(x),
+ static_cast<Z&&>(z)...
+ );
+ }
+ };
+
+ constexpr detail::create<flip_t> flip{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_FLIP_HPP
diff --git a/boost/hana/functional/id.hpp b/boost/hana/functional/id.hpp
new file mode 100644
index 0000000000..e6b4e32b79
--- /dev/null
+++ b/boost/hana/functional/id.hpp
@@ -0,0 +1,38 @@
+/*!
+@file
+Defines `boost::hana::id`.
+
+@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_ID_HPP
+#define BOOST_HANA_FUNCTIONAL_ID_HPP
+
+#include <boost/hana/config.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! The identity function -- returns its argument unchanged.
+ //!
+ //! ### Example
+ //! @include example/functional/id.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto id = [](auto&& x) -> decltype(auto) {
+ return forwarded(x);
+ };
+#else
+ struct id_t {
+ template <typename T>
+ constexpr T operator()(T&& t) const {
+ return static_cast<T&&>(t);
+ }
+ };
+
+ constexpr id_t id{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ID_HPP
diff --git a/boost/hana/functional/infix.hpp b/boost/hana/functional/infix.hpp
new file mode 100644
index 0000000000..471e4f3ac9
--- /dev/null
+++ b/boost/hana/functional/infix.hpp
@@ -0,0 +1,184 @@
+/*!
+@file
+Defines `boost::hana::infix`.
+
+@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_INFIX_HPP
+#define BOOST_HANA_FUNCTIONAL_INFIX_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/functional/reverse_partial.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Return an equivalent function that can also be applied in infix
+ //! notation.
+ //!
+ //! Specifically, `infix(f)` is an object such that:
+ //! @code
+ //! infix(f)(x1, ..., xn) == f(x1, ..., xn)
+ //! x ^infix(f)^ y == f(x, y)
+ //! @endcode
+ //!
+ //! Hence, the returned function can still be applied using the usual
+ //! function call syntax, but it also gains the ability to be applied in
+ //! infix notation. The infix syntax allows a great deal of expressiveness,
+ //! especially when used in combination with some higher order algorithms.
+ //! Since `operator^` is left-associative, `x ^infix(f)^ y` is actually
+ //! parsed as `(x ^infix(f))^ y`. However, for flexibility, the order in
+ //! which both arguments are applied in infix notation does not matter.
+ //! Hence, it is always the case that
+ //! @code
+ //! (x ^ infix(f)) ^ y == x ^ (infix(f) ^ y)
+ //! @endcode
+ //!
+ //! However, note that applying more than one argument in infix
+ //! notation to the same side of the operator will result in a
+ //! compile-time assertion:
+ //! @code
+ //! (infix(f) ^ x) ^ y; // compile-time assertion
+ //! y ^ (x ^ infix(f)); // compile-time assertion
+ //! @endcode
+ //!
+ //! Additionally, a function created with `infix` may be partially applied
+ //! in infix notation. Specifically,
+ //! @code
+ //! (x ^ infix(f))(y1, ..., yn) == f(x, y1, ..., yn)
+ //! (infix(f) ^ y)(x1, ..., xn) == f(x1, ..., xn, y)
+ //! @endcode
+ //!
+ //! @internal
+ //! ### Rationales
+ //! 1. The `^` operator was chosen because it is left-associative and
+ //! has a low enough priority so that most expressions will render
+ //! the expected behavior.
+ //! 2. The operator can't be customimzed because that would require more
+ //! sophistication in the implementation; I want to keep it as simple
+ //! as possible. There is also an advantage in having a uniform syntax
+ //! for infix application.
+ //! @endinternal
+ //!
+ //! @param f
+ //! The function which gains the ability to be applied in infix notation.
+ //! The function must be at least binary; a compile-time error will be
+ //! triggered otherwise.
+ //!
+ //! ### Example
+ //! @include example/functional/infix.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto infix = [](auto f) {
+ return unspecified;
+ };
+#else
+ namespace infix_detail {
+ // This needs to be in the same namespace as `operator^` so it can be
+ // found by ADL.
+ template <bool left, bool right, typename F>
+ struct infix_t {
+ F f;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const&
+ { return f(static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &
+ { return f(static_cast<X&&>(x)...); }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) &&
+ { return std::move(f)(static_cast<X&&>(x)...); }
+ };
+
+ template <bool left, bool right>
+ struct make_infix {
+ template <typename F>
+ constexpr infix_t<left, right, typename std::decay<F>::type>
+ operator()(F&& f) const { return {static_cast<F&&>(f)}; }
+ };
+
+ template <bool left, bool right>
+ struct Infix;
+ struct Object;
+
+ template <typename T>
+ struct dispatch { using type = Object; };
+
+ template <bool left, bool right, typename F>
+ struct dispatch<infix_t<left, right, F>> {
+ using type = Infix<left, right>;
+ };
+
+ template <typename, typename>
+ struct bind_infix;
+
+ // infix(f) ^ y
+ template <>
+ struct bind_infix<Infix<false, false>, Object> {
+ template <typename F, typename Y>
+ static constexpr decltype(auto) apply(F&& f, Y&& y) {
+ return make_infix<false, true>{}(
+ hana::reverse_partial(
+ static_cast<F&&>(f), static_cast<Y&&>(y)
+ )
+ );
+ }
+ };
+
+ // (x^infix(f)) ^ y
+ template <>
+ struct bind_infix<Infix<true, false>, Object> {
+ template <typename F, typename Y>
+ static constexpr decltype(auto) apply(F&& f, Y&& y) {
+ return static_cast<F&&>(f)(static_cast<Y&&>(y));
+ }
+ };
+
+ // x ^ infix(f)
+ template <>
+ struct bind_infix<Object, Infix<false, false>> {
+ template <typename X, typename F>
+ static constexpr decltype(auto) apply(X&& x, F&& f) {
+ return make_infix<true, false>{}(
+ hana::partial(static_cast<F&&>(f), static_cast<X&&>(x))
+ );
+ }
+ };
+
+ // x ^ (infix(f)^y)
+ template <>
+ struct bind_infix<Object, Infix<false, true>> {
+ template <typename X, typename F>
+ static constexpr decltype(auto) apply(X&& x, F&& f) {
+ return static_cast<F&&>(f)(static_cast<X&&>(x));
+ }
+ };
+
+ template <typename T>
+ using strip = typename std::remove_cv<
+ typename std::remove_reference<T>::type
+ >::type;
+
+ template <typename X, typename Y>
+ constexpr decltype(auto) operator^(X&& x, Y&& y) {
+ return bind_infix<
+ typename dispatch<strip<X>>::type,
+ typename dispatch<strip<Y>>::type
+ >::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
+ }
+ } // end namespace infix_detail
+
+ constexpr infix_detail::make_infix<false, false> infix{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_INFIX_HPP
diff --git a/boost/hana/functional/iterate.hpp b/boost/hana/functional/iterate.hpp
new file mode 100644
index 0000000000..b2ec27f5ec
--- /dev/null
+++ b/boost/hana/functional/iterate.hpp
@@ -0,0 +1,201 @@
+/*!
+@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
diff --git a/boost/hana/functional/lockstep.hpp b/boost/hana/functional/lockstep.hpp
new file mode 100644
index 0000000000..fe4a12c7bd
--- /dev/null
+++ b/boost/hana/functional/lockstep.hpp
@@ -0,0 +1,114 @@
+/*!
+@file
+Defines `boost::hana::lockstep`.
+
+@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_LOCKSTEP_HPP
+#define BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the result of invoking other functions on its
+ //! arguments, in lockstep.
+ //!
+ //! Specifically, `lockstep(f)(g1, ..., gN)` is a function such that
+ //! @code
+ //! lockstep(f)(g1, ..., gN)(x1, ..., xN) == f(g1(x1), ..., gN(xN))
+ //! @endcode
+ //!
+ //! Since each `g` is invoked on its corresponding argument in lockstep,
+ //! the number of arguments must match the number of `g`s.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/lockstep.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto lockstep = [](auto&& f, auto&& ...g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(forwarded(g)(forwarded(x))...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...G>
+ struct lockstep_t;
+
+ template <typename F>
+ struct pre_lockstep_t;
+
+ struct make_pre_lockstep_t {
+ struct secret { };
+ template <typename F>
+ constexpr pre_lockstep_t<typename std::decay<F>::type> operator()(F&& f) const {
+ return {static_cast<F&&>(f)};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...G>
+ struct lockstep_t<std::index_sequence<n...>, F, G...> {
+ template <typename ...T>
+ constexpr lockstep_t(make_pre_lockstep_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, G...> storage_;
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)(static_cast<X&&>(x))...
+ );
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<G&&>(hana::get_impl<n+1>(storage_))(static_cast<X&&>(x))...
+ );
+ }
+ };
+
+ template <typename F>
+ struct pre_lockstep_t {
+ F f;
+
+ template <typename ...G>
+ constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename std::decay<G>::type...>
+ operator()(G&& ...g) const& {
+ return {make_pre_lockstep_t::secret{}, this->f, static_cast<G&&>(g)...};
+ }
+
+ template <typename ...G>
+ constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
+ typename std::decay<G>::type...>
+ operator()(G&& ...g) && {
+ return {make_pre_lockstep_t::secret{}, static_cast<F&&>(this->f),
+ static_cast<G&&>(g)...};
+ }
+ };
+
+ constexpr make_pre_lockstep_t lockstep{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
diff --git a/boost/hana/functional/on.hpp b/boost/hana/functional/on.hpp
new file mode 100644
index 0000000000..ff40c0db5c
--- /dev/null
+++ b/boost/hana/functional/on.hpp
@@ -0,0 +1,83 @@
+/*!
+@file
+Defines `boost::hana::on`.
+
+@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_ON_HPP
+#define BOOST_HANA_FUNCTIONAL_ON_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+#include <boost/hana/functional/infix.hpp>
+
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Invoke a function with the result of invoking another function on
+ //! each argument.
+ //!
+ //! Specifically, `on(f, g)` is a function such that
+ //! @code
+ //! on(f, g)(x...) == f(g(x)...)
+ //! @endcode
+ //!
+ //! For convenience, `on` also supports infix application as provided
+ //! by `infix`.
+ //!
+ //!
+ //! @note
+ //! `on` is associative, i.e. `on(f, on(g, h))` is equivalent to
+ //! `on(on(f, g), h)`.
+ //!
+ //! @internal
+ //! ### Proof of associativity
+ //!
+ //! @code
+ //! on(f, on(g, h))(xs...) == f(on(g, h)(xs)...)
+ //! == f(g(h(xs))...)
+ //!
+ //! on(on(f, g), h)(xs...) == on(f, g)(h(xs)...)
+ //! == f(g(h(xs))...)
+ //! @endcode
+ //! @endinternal
+ //!
+ //!
+ //! ### Example
+ //! @include example/functional/on.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto on = infix([](auto&& f, auto&& g) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(f)(g(forwarded(x))...);
+ };
+ });
+#else
+ template <typename F, typename G>
+ struct on_t {
+ F f; G g;
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) const& {
+ return f(g(static_cast<X&&>(x))...);
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) & {
+ return f(g(static_cast<X&&>(x))...);
+ }
+
+ template <typename ...X>
+ constexpr decltype(auto) operator()(X&& ...x) && {
+ return std::move(f)(g(static_cast<X&&>(x))...);
+ }
+ };
+
+ constexpr auto on = infix(detail::create<on_t>{});
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_ON_HPP
diff --git a/boost/hana/functional/overload.hpp b/boost/hana/functional/overload.hpp
new file mode 100644
index 0000000000..b16c87c915
--- /dev/null
+++ b/boost/hana/functional/overload.hpp
@@ -0,0 +1,88 @@
+/*!
+@file
+Defines `boost::hana::overload`.
+
+@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_OVERLOAD_HPP
+#define BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Pick one of several functions to call based on overload resolution.
+ //!
+ //! Specifically, `overload(f1, f2, ..., fn)` is a function object such
+ //! that
+ //! @code
+ //! overload(f1, f2, ..., fn)(x...) == fk(x...)
+ //! @endcode
+ //!
+ //! where `fk` is the function of `f1, ..., fn` that would be called if
+ //! overload resolution was performed amongst that set of functions only.
+ //! If more than one function `fk` would be picked by overload resolution,
+ //! then the call is ambiguous.
+ //!
+ //! ### Example
+ //! @include example/functional/overload.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto overload = [](auto&& f1, auto&& f2, ..., auto&& fn) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(fk)(forwarded(x)...);
+ };
+ };
+#else
+ template <typename F, typename ...G>
+ struct overload_t
+ : overload_t<F>::type
+ , overload_t<G...>::type
+ {
+ using type = overload_t;
+ using overload_t<F>::type::operator();
+ using overload_t<G...>::type::operator();
+
+ template <typename F_, typename ...G_>
+ constexpr explicit overload_t(F_&& f, G_&& ...g)
+ : overload_t<F>::type(static_cast<F_&&>(f))
+ , overload_t<G...>::type(static_cast<G_&&>(g)...)
+ { }
+ };
+
+ template <typename F>
+ struct overload_t<F> { using type = F; };
+
+ template <typename R, typename ...Args>
+ struct overload_t<R(*)(Args...)> {
+ using type = overload_t;
+ R (*fptr_)(Args...);
+
+ explicit constexpr overload_t(R (*fp)(Args...))
+ : fptr_(fp)
+ { }
+
+ constexpr R operator()(Args ...args) const
+ { return fptr_(static_cast<Args&&>(args)...); }
+ };
+
+ struct make_overload_t {
+ template <typename ...F,
+ typename Overload = typename overload_t<
+ typename detail::decay<F>::type...
+ >::type
+ >
+ constexpr Overload operator()(F&& ...f) const {
+ return Overload(static_cast<F&&>(f)...);
+ }
+ };
+
+ constexpr make_overload_t overload{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
diff --git a/boost/hana/functional/overload_linearly.hpp b/boost/hana/functional/overload_linearly.hpp
new file mode 100644
index 0000000000..3695bf2be2
--- /dev/null
+++ b/boost/hana/functional/overload_linearly.hpp
@@ -0,0 +1,105 @@
+/*!
+@file
+Defines `boost::hana::overload_linearly`.
+
+@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_OVERLOAD_LINEARLY_HPP
+#define BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
+
+#include <boost/hana/config.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Call the first function that produces a valid call expression.
+ //!
+ //! Given functions `f1, ..., fn`, `overload_linearly(f1, ..., fn)` is
+ //! a new function that calls the first `fk` producing a valid call
+ //! expression with the given arguments. Specifically,
+ //! @code
+ //! overload_linearly(f1, ..., fn)(args...) == fk(args...)
+ //! @endcode
+ //!
+ //! where `fk` is the _first_ function such that `fk(args...)` is a valid
+ //! expression.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/overload_linearly.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto overload_linearly = [](auto&& f1, auto&& f2, ..., auto&& fn) {
+ return [perfect-capture](auto&& ...x) -> decltype(auto) {
+ return forwarded(fk)(forwarded(x)...);
+ };
+ };
+#else
+ template <typename F, typename G>
+ struct overload_linearly_t {
+ F f;
+ G g;
+
+ private:
+ template <typename ...Args, typename =
+ decltype(std::declval<F const&>()(std::declval<Args>()...))>
+ constexpr F const& which(int) const& { return f; }
+
+ template <typename ...Args, typename =
+ decltype(std::declval<F&>()(std::declval<Args>()...))>
+ constexpr F& which(int) & { return f; }
+
+ template <typename ...Args, typename =
+ decltype(std::declval<F&&>()(std::declval<Args>()...))>
+ constexpr F which(int) && { return static_cast<F&&>(f); }
+
+ template <typename ...Args>
+ constexpr G const& which(long) const& { return g; }
+
+ template <typename ...Args>
+ constexpr G& which(long) & { return g; }
+
+ template <typename ...Args>
+ constexpr G which(long) && { return static_cast<G&&>(g); }
+
+ public:
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) const&
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) &
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+
+ template <typename ...Args>
+ constexpr decltype(auto) operator()(Args&& ...args) &&
+ { return which<Args...>(int{})(static_cast<Args&&>(args)...); }
+ };
+
+ struct make_overload_linearly_t {
+ template <typename F, typename G>
+ constexpr overload_linearly_t<
+ typename std::decay<F>::type,
+ typename std::decay<G>::type
+ > operator()(F&& f, G&& g) const {
+ return {static_cast<F&&>(f), static_cast<G&&>(g)};
+ }
+
+ template <typename F, typename G, typename ...H>
+ constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
+ return (*this)(static_cast<F&&>(f),
+ (*this)(static_cast<G&&>(g), static_cast<H&&>(h)...));
+ }
+ };
+
+ constexpr make_overload_linearly_t overload_linearly{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
diff --git a/boost/hana/functional/partial.hpp b/boost/hana/functional/partial.hpp
new file mode 100644
index 0000000000..c84c365bf9
--- /dev/null
+++ b/boost/hana/functional/partial.hpp
@@ -0,0 +1,107 @@
+/*!
+@file
+Defines `boost::hana::partial`.
+
+@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_PARTIAL_HPP
+#define BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Partially apply a function to some arguments.
+ //!
+ //! Given a function `f` and some arguments, `partial` returns a new
+ //! function corresponding to the partially applied function `f`. This
+ //! allows providing some arguments to a function and letting the rest
+ //! of the arguments be provided later. Specifically, `partial(f, x...)`
+ //! is a function such that
+ //! @code
+ //! partial(f, x...)(y...) == f(x..., y...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(x) + sizeof...(y)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/partial.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto partial = [](auto&& f, auto&& ...x) {
+ return [perfect-capture](auto&& ...y) -> decltype(auto) {
+ return forwarded(f)(forwarded(x)..., forwarded(y)...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...X>
+ struct partial_t;
+
+ struct make_partial_t {
+ struct secret { };
+ template <typename F, typename ...X>
+ constexpr partial_t<
+ std::make_index_sequence<sizeof...(X)>,
+ typename detail::decay<F>::type,
+ typename detail::decay<X>::type...
+ >
+ operator()(F&& f, X&& ...x) const {
+ return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...X>
+ struct partial_t<std::index_sequence<n...>, F, X...> {
+ // Not needed in theory; workaround for a bug in libstdc++'s tuple,
+ // which instantiates the default constructor of elements too eagerly.
+ partial_t() = default;
+
+ template <typename ...T>
+ constexpr partial_t(make_partial_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, X...> storage_;
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) const& {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)...,
+ static_cast<Y&&>(y)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) & {
+ return hana::get_impl<0>(storage_)(
+ hana::get_impl<n+1>(storage_)...,
+ static_cast<Y&&>(y)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<X&&>(hana::get_impl<n+1>(storage_))...,
+ static_cast<Y&&>(y)...
+ );
+ }
+ };
+
+ constexpr make_partial_t partial{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
diff --git a/boost/hana/functional/placeholder.hpp b/boost/hana/functional/placeholder.hpp
new file mode 100644
index 0000000000..71a25389cd
--- /dev/null
+++ b/boost/hana/functional/placeholder.hpp
@@ -0,0 +1,263 @@
+/*!
+@file
+Defines `boost::hana::_`.
+
+@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_PLACEHOLDER_HPP
+#define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/create.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Create simple functions representing C++ operators inline.
+ //!
+ //! Specifically, `_` is an object used as a placeholder to build
+ //! function objects representing calls to C++ operators. It works
+ //! by overloading the operators between `_` and any object so that
+ //! they return a function object which actually calls the corresponding
+ //! operator on its argument(s). Hence, for any supported operator `@`:
+ //! @code
+ //! (_ @ _)(x, y) == x @ y
+ //! @endcode
+ //!
+ //! Operators may also be partially applied to one argument inline:
+ //! @code
+ //! (x @ _)(y) == x @ y
+ //! (_ @ y)(x) == x @ y
+ //! @endcode
+ //!
+ //! When invoked with more arguments than required, functions created with
+ //! `_` will discard the superfluous instead of triggering an error:
+ //! @code
+ //! (_ @ _)(x, y, z...) == x @ y
+ //! @endcode
+ //!
+ //! This makes functions created with `_` easier to use in higher-order
+ //! algorithms, which sometime provide more information than necessary
+ //! to their callbacks.
+ //!
+ //! ### Supported operators
+ //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
+ //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
+ //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
+ //! - %Logical: `||`, `&&`, `!`
+ //! - Member access: `*` (dereference), `[]` (array subscript)
+ //! - Other: `()` (function call)
+ //!
+ //! More complex functionality like the ability to compose placeholders
+ //! into larger function objects inline are not supported. This is on
+ //! purpose; you should either use C++14 generic lambdas or a library
+ //! like [Boost.Phoenix][] if you need bigger guns. The goal here is
+ //! to save you a couple of characters in simple situations.
+ //!
+ //! ### Example
+ //! @include example/functional/placeholder.cpp
+ //!
+ //! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr unspecified _{};
+#else
+ namespace placeholder_detail {
+ template <typename I>
+ struct subscript {
+ I i;
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) const&
+ -> decltype(static_cast<Xs&&>(xs)[i])
+ { return static_cast<Xs&&>(xs)[i]; }
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) &
+ -> decltype(static_cast<Xs&&>(xs)[i])
+ { return static_cast<Xs&&>(xs)[i]; }
+
+ template <typename Xs, typename ...Z>
+ constexpr auto operator()(Xs&& xs, Z const& ...) &&
+ -> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
+ { return static_cast<Xs&&>(xs)[std::move(i)]; }
+ };
+
+ template <typename F, typename Xs, std::size_t ...i>
+ constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
+ return static_cast<F&&>(f)(hana::get_impl<i>(static_cast<Xs&&>(xs).storage_)...);
+ }
+
+ template <typename ...X>
+ struct invoke;
+
+ struct placeholder {
+ struct secret { };
+
+ template <typename X>
+ constexpr decltype(auto) operator[](X&& x) const
+ { return detail::create<subscript>{}(static_cast<X&&>(x)); }
+
+ template <typename ...X>
+ constexpr invoke<typename detail::decay<X>::type...>
+ operator()(X&& ...x) const {
+ return {secret{}, static_cast<X&&>(x)...};
+ }
+ };
+
+ template <typename ...X>
+ struct invoke {
+ template <typename ...Y>
+ constexpr invoke(placeholder::secret, Y&& ...y)
+ : storage_{static_cast<Y&&>(y)...}
+ { }
+
+ basic_tuple<X...> storage_;
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
+ static_cast<F&&>(f)(std::declval<X const&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
+ static_cast<F&&>(f)(std::declval<X&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), *this,
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+
+ template <typename F, typename ...Z>
+ constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
+ static_cast<F&&>(f)(std::declval<X&&>()...)
+ ) {
+ return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
+ std::make_index_sequence<sizeof...(X)>{});
+ }
+ };
+
+#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
+ template <typename X> \
+ struct op_name ## _left { \
+ X x; \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
+ std::declval<X const&>() op static_cast<Y&&>(y)) \
+ { return x op static_cast<Y&&>(y); } \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
+ std::declval<X&>() op static_cast<Y&&>(y)) \
+ { return x op static_cast<Y&&>(y); } \
+ \
+ template <typename Y, typename ...Z> \
+ constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
+ std::declval<X>() op static_cast<Y&&>(y)) \
+ { return std::move(x) op static_cast<Y&&>(y); } \
+ }; \
+ \
+ template <typename Y> \
+ struct op_name ## _right { \
+ Y y; \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y const&>()) \
+ { return static_cast<X&&>(x) op y; } \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y&>()) \
+ { return static_cast<X&&>(x) op y; } \
+ \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
+ static_cast<X&&>(x) op std::declval<Y>()) \
+ { return static_cast<X&&>(x) op std::move(y); } \
+ }; \
+ \
+ struct op_name { \
+ template <typename X, typename Y, typename ...Z> \
+ constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
+ static_cast<X&&>(x) op static_cast<Y&&>(y)) \
+ { return static_cast<X&&>(x) op static_cast<Y&&>(y); } \
+ }; \
+ \
+ template <typename X> \
+ constexpr decltype(auto) operator op (X&& x, placeholder) \
+ { return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); } \
+ \
+ template <typename Y> \
+ constexpr decltype(auto) operator op (placeholder, Y&& y) \
+ { return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); } \
+ \
+ inline constexpr decltype(auto) operator op (placeholder, placeholder) \
+ { return op_name{}; } \
+/**/
+
+#define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name) \
+ struct op_name { \
+ template <typename X, typename ...Z> \
+ constexpr auto operator()(X&& x, Z const& ...) const \
+ -> decltype(op static_cast<X&&>(x)) \
+ { return op static_cast<X&&>(x); } \
+ }; \
+ \
+ inline constexpr decltype(auto) operator op (placeholder) \
+ { return op_name{}; } \
+/**/
+ // Arithmetic
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
+
+ // Bitwise
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
+
+ // Comparison
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
+
+ // Logical
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
+ BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
+
+ // Member access (array subscript is a member function)
+ BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
+
+ // Other (function call is a member function)
+
+#undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
+#undef BOOST_HANA_BINARY_PLACEHOLDER_OP
+ } // end namespace placeholder_detail
+
+ constexpr placeholder_detail::placeholder _{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
diff --git a/boost/hana/functional/reverse_partial.hpp b/boost/hana/functional/reverse_partial.hpp
new file mode 100644
index 0000000000..9a2f63ff23
--- /dev/null
+++ b/boost/hana/functional/reverse_partial.hpp
@@ -0,0 +1,101 @@
+/*!
+@file
+Defines `boost::hana::reverse_partial`.
+
+@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_REVERSE_PARTIAL_HPP
+#define BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP
+
+#include <boost/hana/basic_tuple.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/decay.hpp>
+
+#include <cstddef>
+#include <utility>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! @ingroup group-functional
+ //! Partially apply a function to some arguments.
+ //!
+ //! Given a function `f` and some arguments, `reverse_partial` returns a
+ //! new function corresponding to `f` whose last arguments are partially
+ //! applied. Specifically, `reverse_partial(f, x...)` is a function such
+ //! that
+ //! @code
+ //! reverse_partial(f, x...)(y...) == f(y..., x...)
+ //! @endcode
+ //!
+ //! @note
+ //! The arity of `f` must match the total number of arguments passed to
+ //! it, i.e. `sizeof...(x) + sizeof...(y)`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/functional/reverse_partial.cpp
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto reverse_partial = [](auto&& f, auto&& ...x) {
+ return [perfect-capture](auto&& ...y) -> decltype(auto) {
+ return forwarded(f)(forwarded(y)..., forwarded(x)...);
+ };
+ };
+#else
+ template <typename Indices, typename F, typename ...X>
+ struct reverse_partial_t;
+
+ struct make_reverse_partial_t {
+ struct secret { };
+ template <typename F, typename ...X>
+ constexpr reverse_partial_t<
+ std::make_index_sequence<sizeof...(X)>,
+ typename detail::decay<F>::type,
+ typename detail::decay<X>::type...
+ > operator()(F&& f, X&& ...x) const {
+ return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
+ }
+ };
+
+ template <std::size_t ...n, typename F, typename ...X>
+ struct reverse_partial_t<std::index_sequence<n...>, F, X...> {
+ template <typename ...T>
+ constexpr reverse_partial_t(make_reverse_partial_t::secret, T&& ...t)
+ : storage_{static_cast<T&&>(t)...}
+ { }
+
+ basic_tuple<F, X...> storage_;
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) const& {
+ return hana::get_impl<0>(storage_)(
+ static_cast<Y&&>(y)...,
+ hana::get_impl<n+1>(storage_)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) & {
+ return hana::get_impl<0>(storage_)(
+ static_cast<Y&&>(y)...,
+ hana::get_impl<n+1>(storage_)...
+ );
+ }
+
+ template <typename ...Y>
+ constexpr decltype(auto) operator()(Y&& ...y) && {
+ return static_cast<F&&>(hana::get_impl<0>(storage_))(
+ static_cast<Y&&>(y)...,
+ static_cast<X&&>(hana::get_impl<n+1>(storage_))...
+ );
+ }
+ };
+
+ constexpr make_reverse_partial_t reverse_partial{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP