Boost.Hana  1.5.0
Your standard library for metaprogramming
Functional

Description

General purpose function objects.

Variables

constexpr auto boost::hana::always
 Return a constant function returning x regardless of the argument(s) it is invoked with. More...
 
constexpr auto boost::hana::apply
 Invokes a Callable with the given arguments. More...
 
template<std::size_t n>
constexpr auto boost::hana::arg
 Return the nth passed argument. More...
 
constexpr auto boost::hana::capture
 Create a function capturing the given variables. More...
 
constexpr auto boost::hana::compose
 Return the composition of two functions or more. More...
 
template<std::size_t n>
constexpr auto boost::hana::curry
 Curry a function up to the given number of arguments. More...
 
constexpr auto boost::hana::demux
 Invoke a function with the results of invoking other functions on its arguments. More...
 
constexpr auto boost::hana::fix
 Return a function computing the fixed point of a function. More...
 
constexpr auto boost::hana::flip
 Invoke a function with its two first arguments reversed. More...
 
constexpr auto boost::hana::id
 The identity function – returns its argument unchanged. More...
 
constexpr auto boost::hana::infix
 Return an equivalent function that can also be applied in infix notation. More...
 
template<std::size_t n>
constexpr auto boost::hana::iterate
 Applies another function n times to its argument. More...
 
constexpr auto boost::hana::lockstep
 Invoke a function with the result of invoking other functions on its arguments, in lockstep. More...
 
constexpr auto boost::hana::on
 Invoke a function with the result of invoking another function on each argument. More...
 
constexpr auto boost::hana::overload
 Pick one of several functions to call based on overload resolution. More...
 
constexpr auto boost::hana::overload_linearly
 Call the first function that produces a valid call expression. More...
 
constexpr auto boost::hana::partial
 Partially apply a function to some arguments. More...
 
constexpr unspecified boost::hana::_ {}
 Create simple functions representing C++ operators inline. More...
 
constexpr auto boost::hana::reverse_partial
 Partially apply a function to some arguments. More...
 

Variable Documentation

constexpr auto boost::hana::always

#include <boost/hana/functional/always.hpp>

Initial value:
= [](auto&& x) {
return [perfect-capture](auto const& ...y) -> decltype(auto) {
return forwarded(x);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

Return a constant function returning x regardless of the argument(s) it is invoked with.

Specifically, always(x) is a function such that

always(x)(y...) == x

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

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::always(1)() == 1, "");
static_assert(hana::always('2')(1, 2, 3) == '2', "");
int main() { }
constexpr auto boost::hana::apply

#include <boost/hana/functional/apply.hpp>

Initial value:
= [](auto&& f, auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(x)...);
}

Invokes a Callable with the given arguments.

This is equivalent to std::invoke 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.

Parameters
fA Callable to be invoked with the given arguments.
x...The arguments to call f with. The number of x... must match the arity of f.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::apply(hana::plus, 1, 2) == 3, "");
int main() { }

Referenced by boost::hana::literals::operator""_c(), and boost::hana::literals::operator""_s().

template<std::size_t n>
constexpr auto boost::hana::arg

#include <boost/hana/functional/arg.hpp>

Initial value:
= [](auto&& x1, ..., auto&& xm) -> decltype(auto) {
return forwarded(xn);
}

Return the nth 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.

Template Parameters
nAn unsigned integer representing the argument to return. n must be positive (meaning nonzero).
Parameters
x1,...,xmA variadic pack of arguments from which the nth one is returned.

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.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
// hana::arg<0>(1, '2', 3.3); // static assertion (regardless of the number of arguments)
static_assert(hana::arg<1>(1, '2', 3.3) == 1, "");
static_assert(hana::arg<2>(1, '2', 3.3) == '2', "");
static_assert(hana::arg<3>(1, '2', 3.3) == 3.3, "");
// hana::arg<4>(1, '2', 3.3); // static assertion
int main() { }
constexpr auto boost::hana::capture

#include <boost/hana/functional/capture.hpp>

Initial value:
= [](auto&& ...variables) {
return [perfect-capture](auto&& f) {
return [perfect-capture](auto&& ...args) -> decltype(auto) {
return forwarded(f)(forwarded(variables)..., forwarded(args)...);
};
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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,

capture(vars...)(f)(args...) == f(vars..., args...)
Note
The arity of f must match the total number of arguments passed to it, i.e. sizeof...(vars) + sizeof...(args).

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto sum = [](auto x, auto y, auto z) {
return x + y + z;
};
}
constexpr auto boost::hana::compose

#include <boost/hana/functional/compose.hpp>

Initial value:
= [](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)...
);
}
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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

compose(f, g)(x, y...) == f(g(x), y...)

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).

Proof of associativity

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...)

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto to_char = [](int x) {
return static_cast<char>(x + 48);
};
BOOST_HANA_CONSTEXPR_LAMBDA auto increment = [](auto x) {
return x + 1;
};
BOOST_HANA_CONSTEXPR_CHECK(hana::compose(to_char, increment)(3) == '4');
}
template<std::size_t n>
constexpr auto boost::hana::curry

#include <boost/hana/functional/curry.hpp>

Initial value:
= [](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)
);
};
};
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

Curry a function up to the given number of arguments.

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

(X1, ..., Xn) -> R

Then, currying is the process of taking f and turning it into an equivalent function (call it g) of type

X1 -> (X2 -> (... -> (Xn -> R)))

This gives us the following equivalence, where x1, ..., xn are objects of type X1, ..., Xn respectively:

f(x1, ..., xn) == g(x1)...(xn)

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

curry<n>(f)(x1)...(xn) == f(x1, ..., xn)

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

curry<n>(f)(x1, ..., xk) == curry<n - k>(f)(x1)...(xk)

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

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto add = [](auto x, auto y, auto z) {
return x + y + z;
};
BOOST_HANA_CONSTEXPR_CHECK(hana::curry<3>(add)(1)(2)(3) == 1 + 2 + 3);
BOOST_HANA_CONSTEXPR_CHECK(hana::curry<3>(add)(1)(2, 3) == hana::curry<3>(add)(1)(2)(3));
BOOST_HANA_CONSTEXPR_CHECK(hana::curry<3>(add)(1, 2, 3) == hana::curry<3>(add)(1)(2)(3));
// curry with a nullary function
BOOST_HANA_CONSTEXPR_LAMBDA auto two = []() {
return 2;
};
BOOST_HANA_CONSTEXPR_CHECK(hana::curry<0>(two)() == two());
}
constexpr auto boost::hana::demux

#include <boost/hana/functional/demux.hpp>

Initial value:
= [](auto&& f) {
return [perfect-capture](auto&& ...g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(g)(x...)...);
};
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

Invoke a function with the results of invoking other functions on its arguments.

Specifically, demux(f)(g...) is a function such that

demux(f)(g...)(x...) == f(g(x...)...)

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 gs.

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

\[ \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) \]

This can be rewritten more tersely as

\[ \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) \]

Link with normal composition

The signature of compose is

\[ \mathtt{compose} : (B \to C) \times (A \to B) \to (A \to C) \]

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:

demux(f)(g)(x) == compose(f, g)(x)

However, let's now consider the curried version of compose, curry<2>(compose):

\[ \mathtt{curry_2(compose)} : (B \to C) \to ((A \to B) \to (A \to C)) \]

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:

\[ \mathtt{compose(compose, compose)} : (B \to C) \to (A_1 \to A_2 \to B) \to (A_1 \to A_2 \to C) \]

If we uncurry deeply the above expression, we obtain

\[ \mathtt{compose(compose, compose)} : (B \to C) \times (A_1 \times A_2 \to B) \to (A_1 \times A_2 \to C) \]

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):

\[ \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) \]

which uncurries to

\[ \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) \]

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:

demux(f)(g) == fold_left([compose, ..., compose], id, compose)(g, f)
// ^^^^^^^^^^^^^^^^^^^^^ n times

More information on this insight can be seen here. 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

demux(f)(demux(g)(h))(x...) == f(demux(g)(h)(x...))
== f(g(h(x...)))

On the other hand, we have

demux(demux(f)(g))(h)(x...) == demux(f)(g)(h(x...))
== f(g(h(x...)))

and hence demux is associative in the binary case.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
using hana::_;
constexpr auto f = hana::demux(hana::make_tuple)(
_ + _,
_ - _,
_ * _,
_ / _
);
static_assert(
f(10, 4) == hana::make_tuple(
10 + 4,
10 - 4,
10 * 4,
10 / 4
)
, "");
int main() { }
constexpr auto boost::hana::fix

#include <boost/hana/functional/fix.hpp>

Initial value:
= [](auto&& f) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(fix(f), forwarded(x)...);
};
}
constexpr auto fix
Return a function computing the fixed point of a function.
Definition: fix.hpp:53
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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

fix(f)(x...) == f(fix(f), x...)

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.

Parameters
fA function called as f(self, x...), where x... are the arguments in the fix(f)(x...) expression and self is fix(f).

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTEXPR_STATELESS_LAMBDA auto factorial = hana::fix([](auto fact, auto n) -> int {
if (n == 0) return 1;
else return n * fact(n - 1);
});
int main() {
BOOST_HANA_CONSTEXPR_CHECK(factorial(5) == 120);
}
constexpr auto boost::hana::flip

#include <boost/hana/functional/flip.hpp>

Initial value:
= [](auto&& f) {
return [perfect-capture](auto&& x, auto&& y, auto&& ...z) -> decltype(auto) {
return forwarded(f)(forwarded(y), forwarded(x), forwarded(z)...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

Invoke a function with its two first arguments reversed.

Specifically, flip(f) is a function such that

flip(f)(x, y, z...) == f(y, x, z...)

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTEXPR_LAMBDA auto minus = [](int x, int y, int z = 0) {
return x - y - z;
};
int main() {
BOOST_HANA_CONSTEXPR_CHECK(hana::flip(minus)(3, 0) == 0 - 3);
BOOST_HANA_CONSTEXPR_CHECK(minus(3, 0, 1) == 3 - 0 - 1);
BOOST_HANA_CONSTEXPR_CHECK(hana::flip(minus)(3, 0, 1) == 0 - 3 - 1);
}
constexpr auto boost::hana::id

#include <boost/hana/functional/id.hpp>

Initial value:
= [](auto&& x) -> decltype(auto) {
return forwarded(x);
}

The identity function – returns its argument unchanged.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::id(1) == 1, "");
static_assert(hana::id('x') == 'x', "");
int main() { }
constexpr auto boost::hana::infix

#include <boost/hana/functional/infix.hpp>

Initial value:
= [](auto f) {
return unspecified;
}

Return an equivalent function that can also be applied in infix notation.

Specifically, infix(f) is an object such that:

infix(f)(x1, ..., xn) == f(x1, ..., xn)
x ^infix(f)^ y == f(x, y)

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

(x ^ infix(f)) ^ y == x ^ (infix(f) ^ y)

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:

(infix(f) ^ x) ^ y; // compile-time assertion
y ^ (x ^ infix(f)); // compile-time assertion

Additionally, a function created with infix may be partially applied in infix notation. Specifically,

(x ^ infix(f))(y1, ..., yn) == f(x, y1, ..., yn)
(infix(f) ^ y)(x1, ..., xn) == f(x1, ..., xn, y)

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.
Parameters
fThe 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

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTEXPR_LAMBDA auto divmod = hana::infix([](auto x, auto y) {
// this could be a more efficient implementation
return hana::make_pair(x / y, x % y);
});
int main() {
BOOST_HANA_CONSTEXPR_CHECK((42 ^divmod^ 23) == hana::make_pair(1, 19));
}
template<std::size_t n>
constexpr auto boost::hana::iterate

#include <boost/hana/functional/iterate.hpp>

Initial value:
= [](auto&& f) {
return [perfect-capture](auto&& x) -> decltype(auto) {
return f(f( ... f(forwarded(x))));
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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,

iterate<n>(f, x) == f(f( ... f(x)))
^^^^^^^^^^ n times total

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

iterate<n>(f)(x) == iterate<n>(f, x)

This is provided for convenience, and it turns out to be especially useful in conjunction with higher-order algorithms.

Signature

Given a function \( f : T \to T \) and x and argument of data type T, the signature is \( \mathtt{iterate_n} : (T \to T) \times T \to T \)

Template Parameters
nAn unsigned integer representing the number of times that f should be applied to its argument.
Parameters
fA function to apply n times to its argument.
xThe initial value to call f with.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto next_10 = hana::iterate<10>(hana::_ + 1);
static_assert(next_10(3) == 13, "");
constexpr auto xs = hana::make_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
static_assert(hana::iterate<3>(hana::make_tuple, xs) ==
hana::make_tuple(hana::make_tuple(hana::make_tuple(xs))), "");
int main() { }
constexpr auto boost::hana::lockstep

#include <boost/hana/functional/lockstep.hpp>

Initial value:
= [](auto&& f, auto&& ...g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(g)(forwarded(x))...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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

lockstep(f)(g1, ..., gN)(x1, ..., xN) == f(g1(x1), ..., gN(xN))

Since each g is invoked on its corresponding argument in lockstep, the number of arguments must match the number of gs.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr int to_int(char c) {
return static_cast<int>(c) - 48;
}
constexpr int increment(int i) {
return i + 1;
}
static_assert(hana::lockstep(hana::plus)(to_int, increment)('3', 4) == 3 + 5, "");
int main() { }
constexpr auto boost::hana::on

#include <boost/hana/functional/on.hpp>

Initial value:
= infix([](auto&& f, auto&& g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(g(forwarded(x))...);
};
})
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45
constexpr auto infix
Return an equivalent function that can also be applied in infix notation.
Definition: infix.hpp:79

Invoke a function with the result of invoking another function on each argument.

Specifically, on(f, g) is a function such that

on(f, g)(x...) == f(g(x)...)

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).

Proof of associativity

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))...)

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
// infix application
constexpr auto sorted = hana::sort.by(hana::less ^hana::on^ hana::first, hana::make_tuple(
hana::make_pair(hana::int_c<3>, 'x'),
hana::make_pair(hana::int_c<1>, hana::type_c<void>),
hana::make_pair(hana::int_c<2>, 9876)
));
static_assert(sorted == hana::make_tuple(
hana::make_pair(hana::int_c<1>, hana::type_c<void>),
hana::make_pair(hana::int_c<2>, 9876),
hana::make_pair(hana::int_c<3>, 'x')
), "");
// function call syntax
constexpr auto x = hana::make_pair(1, 2);
constexpr auto y = hana::make_pair(10, 20);
static_assert(hana::on(hana::plus, hana::first)(x, y) == 1 + 10, "");
int main() { }
constexpr auto boost::hana::overload

#include <boost/hana/functional/overload.hpp>

Initial value:
= [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(fk)(forwarded(x)...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

Pick one of several functions to call based on overload resolution.

Specifically, overload(f1, f2, ..., fn) is a function object such that

overload(f1, f2, ..., fn)(x...) == fk(x...)

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

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <iostream>
#include <string>
namespace hana = boost::hana;
auto on_string = [](std::string const& s) {
std::cout << "matched std::string: " << s << std::endl;
return s;
};
auto on_int = [](int i) {
std::cout << "matched int: " << i << std::endl;
return i;
};
auto f = hana::overload(on_int, on_string);
int main() {
// prints "matched int: 1"
// prints "matched std::string: abcdef"
BOOST_HANA_RUNTIME_CHECK(f("abcdef") == std::string{"abcdef"});
}
constexpr auto boost::hana::overload_linearly

#include <boost/hana/functional/overload_linearly.hpp>

Initial value:
= [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(fk)(forwarded(x)...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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,

overload_linearly(f1, ..., fn)(args...) == fk(args...)

where fk is the first function such that fk(args...) is a valid expression.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <string>
namespace hana = boost::hana;
[](int i) { return i + 1; },
[](std::string s) { return s + "d"; },
[](double) { BOOST_HANA_RUNTIME_CHECK(false && "never called"); }
);
int main() {
BOOST_HANA_RUNTIME_CHECK(f("abc") == "abcd");
BOOST_HANA_RUNTIME_CHECK(f(2.2) == static_cast<int>(2.2) + 1);
}
constexpr auto boost::hana::partial

#include <boost/hana/functional/partial.hpp>

Initial value:
= [](auto&& f, auto&& ...x) {
return [perfect-capture](auto&& ...y) -> decltype(auto) {
return forwarded(f)(forwarded(x)..., forwarded(y)...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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

partial(f, x...)(y...) == f(x..., y...)
Note
The arity of f must match the total number of arguments passed to it, i.e. sizeof...(x) + sizeof...(y).

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto increment = hana::partial(hana::plus, 1);
static_assert(increment(2) == 3, "");
int main() { }
constexpr unspecified boost::hana::_ {}

#include <boost/hana/functional/placeholder.hpp>

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 @:

(_ @ _)(x, y) == x @ y

Operators may also be partially applied to one argument inline:

(x @ _)(y) == x @ y
(_ @ y)(x) == x @ y

When invoked with more arguments than required, functions created with _ will discard the superfluous instead of triggering an error:

(_ @ _)(x, y, z...) == x @ y

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

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto plus = hana::_ + hana::_;
static_assert(plus(1, 2) == 1 + 2, "");
constexpr auto increment = hana::_ + 1;
static_assert(increment(1) == 2, "");
constexpr auto twice = 2 * hana::_;
static_assert(twice(1) == 2, "");
// Extra arguments are ignored.
static_assert(twice(1, "ignored") == 2, "");
int main() { }
constexpr auto boost::hana::reverse_partial

#include <boost/hana/functional/reverse_partial.hpp>

Initial value:
= [](auto&& f, auto&& ...x) {
return [perfect-capture](auto&& ...y) -> decltype(auto) {
return forwarded(f)(forwarded(y)..., forwarded(x)...);
};
}
constexpr auto capture
Create a function capturing the given variables.
Definition: capture.hpp:45

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

reverse_partial(f, x...)(y...) == f(y..., x...)
Note
The arity of f must match the total number of arguments passed to it, i.e. sizeof...(x) + sizeof...(y).

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto half = hana::reverse_partial(hana::div, 2);
static_assert(half(4) == 2, "");
static_assert(half(8) == 4, "");
int main() { }