Boost.Hana: Iterable

| Boost.Hana 1.0.0 Your standard library for metaprogramming |

Variables
Iterable
Concepts

## Description

The `Iterable` concept represents data structures supporting external iteration.

Intuitively, an `Iterable` can be seen as a kind of container whose elements can be pulled out one at a time. An `Iterable` also provides a way to know when the container is empty, i.e. when there are no more elements to pull out.

Whereas `Foldable` represents data structures supporting internal iteration with the ability to accumulate a result, the `Iterable` concept allows inverting the control of the iteration. This is more flexible than `Foldable`, since it allows iterating over only some part of the structure. This, in turn, allows `Iterable` to work on infinite structures, while trying to fold such a structure would never finish.

## Minimal complete definition

`at`, `drop_front` and `is_empty`

## The linearization of an `Iterable`

Intuitively, for an `Iterable` structure `xs`, the linearization of `xs` is the sequence of all the elements in `xs` as if they had been put in a (possibly infinite) list:

linearization(xs) = [x1, x2, x3, ...]

The `n`th element of the linearization of an `Iterable` can be accessed with the `at` function. In other words, `at(xs, n) == xn`.

Note that this notion is precisely the extension of the linearization notion of `Foldable`s to the infinite case. This notion is useful for expressing various properties of `Iterable`s, and is used for that elsewhere in the documentation.

## Compile-time `Iterable`s

A compile-time `Iterable` is an `Iterable` for which `is_empty` returns a compile-time `Logical`. These structures allow iteration to be done at compile-time, in the sense that the "loop" doing the iteration can be unrolled because the total length of the structure is kown at compile-time.

In particular, note that being a compile-time `Iterable` has nothing to do with being finite or infinite. For example, it would be possible to create a sequence representing the Pythagorean triples as `integral_constant`s. Such a sequence would be infinite, but iteration on the sequence would still be done at compile-time. However, if one tried to iterate over all the elements of the sequence, the compiler would loop indefinitely, in contrast to your program looping indefinitely if the sequence was a runtime one.

In the current version of the library, only compile-time `Iterable`s are supported. While it would be possible in theory to support runtime `Iterable`s, doing it efficiently is the subject of some research. In particular, follow this issue for the current status of runtime `Iterable`s.

## Laws

First, we require the equality of two `Iterable`s to be related to the equality of the elements in their linearizations. More specifically, if `xs` and `ys` are two `Iterable`s of data type `It`, then

xs == ys => at(xs, i) == at(ys, i) for all i

This conveys that two `Iterable`s must have the same linearization in order to be considered equal.

Secondly, since every `Iterable` is also a `Searchable`, we require the models of `Iterable` and `Searchable` to be consistent. This is made precise by the following laws. For any `Iterable` `xs` with a linearization of `[x1, x2, x3, ...]`,

any_of(xs, equal.to(z)) <=> xi == z

for some finite index `i`. Furthermore,

find_if(xs, pred) == just(the first xi such that pred(xi) is satisfied)

or `nothing` if no such `xi` exists.

## Refined concepts

1. `Searchable` (free model)
   Any `Iterable` gives rise to a model of `Searchable`, where the keys and the values are both the elements in the structure. Searching for a key is just doing a linear search through the elements of the structure.
   // 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)
   #include <boost/hana/assert.hpp>
   #include <boost/hana/ext/std/integral_constant.hpp>
   #include <boost/hana/find.hpp>
   #include <boost/hana/find_if.hpp>
   #include <boost/hana/functional/compose.hpp>
   #include <boost/hana/integral_constant.hpp>
   #include <boost/hana/optional.hpp>
   #include <boost/hana/tuple.hpp>
   #include <boost/hana/type.hpp>
   #include <type_traits>
   namespace hana = boost::hana;
   // First get the type of the object, and then call the trait on it.
   constexpr auto is_integral = hana::compose(hana::trait<std::is_integral>, hana::decltype_);
   constexpr auto is_class = hana::compose(hana::trait<std::is_class>, hana::decltype_);
   static_assert(
   hana::find_if(hana::make_tuple(1.0, 2, '3'), is_integral)
   ==
   hana::just(2)
   , "");
   BOOST_HANA_CONSTANT_CHECK(
   hana::find_if(hana::make_tuple(1.0, 2, '3'), is_class)
   ==
   hana::nothing
   );
   BOOST_HANA_CONSTANT_CHECK(
   hana::find(hana::make_tuple(hana::int_c<1>, hana::char_c<'c'>, hana::type_c<void>), hana::type_c<void>)
   ==
   hana::just(hana::type_c<void>)
   );
   BOOST_HANA_CONSTANT_CHECK(
   hana::find(hana::make_tuple(hana::int_c<1>, hana::char_c<'c'>, hana::type_c<void>), hana::type_c<int>)
   ==
   hana::nothing
   );
   int main() { }
2. `Foldable` for finite `Iterable`s
   Every finite `Iterable` gives rise to a model of `Foldable`. For these models to be consistent, we require the models of both `Foldable` and `Iterable` to have the same linearization.

Note
  As explained above, `Iterable`s are also `Searchable`s and their models have to be consistent. By the laws presented here, it also means that the `Foldable` model for finite `Iterable`s has to be consistent with the `Searchable` model.

For convenience, finite `Iterable`s must only provide a definition of `length` to model the `Foldable` concept; defining the more powerful `unpack` or `fold_left` is not necessary (but still possible). The default implementation of `unpack` derived from `Iterable` + `length` uses the fact that `at(xs, i)` denotes the `i`th element of `xs`'s linearization, and that the linearization of a finite `Iterable` must be the same as its linearization as a `Foldable`.

## Concrete models

`hana::tuple`, `hana::string`, `hana::range`

## Variables
constexpr auto | boost::hana::at
| Returns the `n`th element of an iterable.Given an `Iterable` and an `IntegralConstant` index, `at` returns the element located at the index in the linearization of the iterable. Specifically, given an iterable `xs` with a linearization of `[x1, ..., xN]`, `at(xs, k)` is equivalent to `xk`. More...
template<std::size_t n>
constexpr auto | boost::hana::at_c
| Equivalent to `at`; provided for convenience. More...
constexpr auto | boost::hana::back
| Returns the last element of a non-empty and finite iterable.Given a non-empty and finite iterable `xs` with a linearization of `[x1, ..., xN]`, `back(xs)` is equal to `xN`. Equivalently, `back(xs)` must be equivalent to `at_c<N-1>(xs)`, and that regardless of the value category of `xs` (`back` must respect the reference semantics of `at`). More...
constexpr auto | boost::hana::drop_front
| Drop the first `n` elements of an iterable, and return the rest.Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and a non-negative `IntegralConstant` `n`, `drop_front(xs, n)` is an iterable with the same tag as `xs` whose linearization is `[xn+1, xn+2, ...]`. In particular, note that this function does not mutate the original iterable in any way. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`. More...
constexpr auto | boost::hana::drop_front_exactly
| Drop the first `n` elements of an iterable, and return the rest.Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and a non-negative `IntegralConstant` `n`, `drop_front_exactly(xs, n)` is an iterable with the same tag as `xs` whose linearization is `[xn+1, xn+2, ...]`. In particular, note that this function does not mutate the original iterable in any way. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`. More...
constexpr auto | boost::hana::drop_while
| Drop elements from an iterable up to, but excluding, the first element for which the `predicate` is not satisfied.Specifically, `drop_while` returns an iterable containing all the elements of the original iterable except for those in the range delimited by [`head`, `e`), where `head` is the first element and `e` is the first element for which the `predicate` is not satisfied. If the iterable is not finite, the `predicate` has to return a false- valued `Logical` at a finite index for this method to return. More...
constexpr auto | boost::hana::front
| Returns the first element of a non-empty iterable.Given a non-empty Iterable `xs` with a linearization of `[x1, ..., xN]`, `front(xs)` is equal to `x1`. If `xs` is empty, it is an error to use this function. Equivalently, `front(xs)` must be equivalent to `at_c<0>(xs)`, and that regardless of the value category of `xs` (`front` must respect the reference semantics of `at`). More...
constexpr auto | boost::hana::is_empty
| Returns whether the iterable is empty.Given an `Iterable` `xs`, `is_empty` returns whether `xs` contains no more elements. In other words, it returns whether trying to extract the tail of `xs` would be an error. In the current version of the library, `is_empty` must return an `IntegralConstant` holding a value convertible to `bool`. This is because only compile-time `Iterable`s are supported right now. More...
constexpr auto | boost::hana::lexicographical_compare
| Short-circuiting lexicographical comparison of two `Iterable`s with an optional custom predicate, by default `hana::less`.Given two `Iterable`s `xs` and `ys` and a binary predicate `pred`, `lexicographical_compare` returns whether `xs` is to be considered less than `ys` in a lexicographical ordering. Specifically, let's denote the linearizations of `xs` and `ys` by `[x1, x2, ...]` and `[y1, y2, ...]`, respectively. If the first couple satisfying the predicate is of the form `xi, yi`, `lexicographical_compare` returns true. Otherwise, if the first couple to satisfy the predicate is of the form `yi, xi`, `lexicographical_compare` returns false. If no such couple can be found, `lexicographical_compare` returns whether `xs` has fewer elements than `ys`. More...

## Variable Documentation

constexpr auto boost::hana::at

`#include <boost/hana/fwd/at.hpp>`

Initial value:
= [](auto&& xs, auto const& n) -> decltype(auto) {
return tag-dispatched;
}

Returns the `n`th element of an iterable.Given an `Iterable` and an `IntegralConstant` index, `at` returns the element located at the index in the linearization of the iterable. Specifically, given an iterable `xs` with a linearization of `[x1, ..., xN]`, `at(xs, k)` is equivalent to `xk`.

If the `Iterable` actually stores the elements it contains, `at` is required to return a lvalue reference, a lvalue reference to const or a rvalue reference to the matching element, where the type of reference must match that of the iterable passed to `at`. If the `Iterable` does not store the elements it contains (i.e. it generates them on demand), this requirement is dropped.

Parameters

  xs | The iterable in which an element is retrieved. The iterable must contain at least `n + 1` elements.
  n | A non-negative `IntegralConstant` representing the 0-based index of the element to return. It is an error to call `at` with an index that out of bounds of the iterable.

## Example

// 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)
#include <boost/hana/at.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
constexpr auto xs = hana::make_tuple(0, '1', 2.0);
static_assert(hana::at(xs, hana::size_c<0>) == 0, "");
static_assert(hana::at(xs, hana::size_c<1>) == '1', "");
static_assert(hana::at(xs, hana::size_c<2>) == 2.0, "");
int main() { }

## Benchmarks

template<std::size_t n>

constexpr auto boost::hana::at_c

`#include <boost/hana/fwd/at.hpp>`

Initial value:
= [](auto&& xs) {
return hana::at(forwarded(xs), hana::size_c<n>);
}
boost::hana::at
constexpr auto at
Returns the nth element of an iterable.Given an Iterable and an IntegralConstant index, at returns the element located at the index in the linearization of the iterable. Specifically, given an iterable xs with a linearization of [x1, ..., xN], at(xs, k) is equivalent to xk.
Definition: at.hpp:58

Equivalent to `at`; provided for convenience.

Note
  `hana::at_c<n>` is an overloaded function, not a function object. Hence, it can't be passed to higher-order algorithms. This is done for compile-time performance reasons.

## Example

// 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)
#include <boost/hana/at.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
constexpr auto xs = hana::make_tuple(0, '1', 2.0);
static_assert(hana::at_c<0>(xs) == 0, "");
static_assert(hana::at_c<1>(xs) == '1', "");
static_assert(hana::at_c<2>(xs) == 2.0, "");
int main() { }

constexpr auto boost::hana::back

`#include <boost/hana/fwd/back.hpp>`

Initial value:
= [](auto&& xs) -> decltype(auto) {
return tag-dispatched;
}

Returns the last element of a non-empty and finite iterable.Given a non-empty and finite iterable `xs` with a linearization of `[x1, ..., xN]`, `back(xs)` is equal to `xN`. Equivalently, `back(xs)` must be equivalent to `at_c<N-1>(xs)`, and that regardless of the value category of `xs` (`back` must respect the reference semantics of `at`).

## Example

// 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)
#include <boost/hana/back.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
static_assert(hana::back(hana::make_tuple(1, '2', 3.3)) == 3.3, "");
static_assert(hana::back(hana::make_tuple(1, '2', 3.3, nullptr)) == nullptr, "");
int main() { }

constexpr auto boost::hana::drop_front

`#include <boost/hana/fwd/drop_front.hpp>`

Initial value:
= [](auto&& xs[, auto const& n]) {
return tag-dispatched;
}

Drop the first `n` elements of an iterable, and return the rest.Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and a non-negative `IntegralConstant` `n`, `drop_front(xs, n)` is an iterable with the same tag as `xs` whose linearization is `[xn+1, xn+2, ...]`. In particular, note that this function does not mutate the original iterable in any way. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`.

In case `length(xs) <= n`, `drop_front` will simply drop the whole iterable without failing, thus returning an empty iterable. This is different from `drop_front_exactly`, which expects `n <= length(xs)` but can be better optimized because of this additional guarantee.

Parameters

  xs | The iterable from which elements are dropped.
  n | A non-negative `IntegralConstant` representing the number of elements to be dropped from the iterable. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`.

## Example

// 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)
#include <boost/hana/assert.hpp>
#include <boost/hana/drop_front.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
constexpr auto xs = hana::make_tuple(0, '1', 2.0);
static_assert(hana::drop_front(xs, hana::size_c<0>) == xs, "");
static_assert(hana::drop_front(xs, hana::size_c<1>) == hana::make_tuple('1', 2.0), "");
static_assert(hana::drop_front(xs, hana::size_c<2>) == hana::make_tuple(2.0), "");
BOOST_HANA_CONSTANT_CHECK(hana::drop_front(xs, hana::size_c<3>) == hana::make_tuple());
BOOST_HANA_CONSTANT_CHECK(hana::drop_front(xs, hana::size_c<4>) == hana::make_tuple());
// drop_front(xs) is equivalent to drop_front(xs, size_t<1>)
static_assert(hana::drop_front(xs) == hana::make_tuple('1', 2.0), "");
int main() { }

constexpr auto boost::hana::drop_front_exactly

`#include <boost/hana/fwd/drop_front_exactly.hpp>`

Initial value:
= [](auto&& xs[, auto const& n]) {
return tag-dispatched;
}

Drop the first `n` elements of an iterable, and return the rest.Given an `Iterable` `xs` with a linearization of `[x1, x2, ...]` and a non-negative `IntegralConstant` `n`, `drop_front_exactly(xs, n)` is an iterable with the same tag as `xs` whose linearization is `[xn+1, xn+2, ...]`. In particular, note that this function does not mutate the original iterable in any way. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`.

It is an error to use `drop_front_exactly` with `n > length(xs)`. This additional guarantee allows `drop_front_exactly` to be better optimized than the `drop_front` function, which allows `n > length(xs)`.

Parameters

  xs | The iterable from which elements are dropped.
  n | A non-negative `IntegralConstant` representing the number of elements to be dropped from the iterable. In addition to being non-negative, `n` must be less than or equal to the number of elements in `xs`. If `n` is not given, it defaults to an `IntegralConstant` with a value equal to `1`.

## Example

// 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)
#include <boost/hana/assert.hpp>
#include <boost/hana/drop_front_exactly.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
constexpr auto xs = hana::make_tuple(0, '1', 2.0);
static_assert(hana::drop_front_exactly(xs, hana::size_c<1>) == hana::make_tuple('1', 2.0), "");
static_assert(hana::drop_front_exactly(xs, hana::size_c<2>) == hana::make_tuple(2.0), "");
BOOST_HANA_CONSTANT_CHECK(hana::drop_front_exactly(xs, hana::size_c<3>) == hana::make_tuple());
// drop_front_exactly(xs) is equivalent to drop_front_exactly(xs, size_t<1>)
static_assert(hana::drop_front_exactly(xs) == hana::make_tuple('1', 2.0), "");
int main() { }

constexpr auto boost::hana::drop_while

`#include <boost/hana/fwd/drop_while.hpp>`

Initial value:
= [](auto&& iterable, auto&& predicate) {
return tag-dispatched;
}

Drop elements from an iterable up to, but excluding, the first element for which the `predicate` is not satisfied.Specifically, `drop_while` returns an iterable containing all the elements of the original iterable except for those in the range delimited by [`head`, `e`), where `head` is the first element and `e` is the first element for which the `predicate` is not satisfied. If the iterable is not finite, the `predicate` has to return a false- valued `Logical` at a finite index for this method to return.

Parameters

  iterable | The iterable from which elements are dropped.
  predicate | A function called as `predicate(x)`, where `x` is an element of the structure, and returning a `Logical` representing whether `x` should be dropped from the structure. In the current version of the library, `predicate` should return a compile-time `Logical`.

## Example

// 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)
#include <boost/hana/assert.hpp>
#include <boost/hana/drop_while.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/less.hpp>
#include <boost/hana/negate.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
using namespace hana::literals;
auto negative = [](auto x) {
return x < hana::int_c<0>;
};
BOOST_HANA_CONSTANT_CHECK(
hana::drop_while(hana::make_range(hana::int_c<-3>, hana::int_c<6>), negative)
==
hana::make_range(hana::int_c<0>, hana::int_c<6>)
);
BOOST_HANA_CONSTANT_CHECK(
hana::drop_while(hana::make_tuple(1_c, -2_c, 4_c, 5_c), negative)
==
hana::make_tuple(1_c, -2_c, 4_c, 5_c)
);
int main() { }

constexpr auto boost::hana::front

`#include <boost/hana/fwd/front.hpp>`

Initial value:
= [](auto&& xs) -> decltype(auto) {
return tag-dispatched;
}

Returns the first element of a non-empty iterable.Given a non-empty Iterable `xs` with a linearization of `[x1, ..., xN]`, `front(xs)` is equal to `x1`. If `xs` is empty, it is an error to use this function. Equivalently, `front(xs)` must be equivalent to `at_c<0>(xs)`, and that regardless of the value category of `xs` (`front` must respect the reference semantics of `at`).

## Example

// 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)
#include <boost/hana/front.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
static_assert(hana::front(hana::make_tuple(1, '2', 3.3, nullptr)) == 1, "");
int main() { }

constexpr auto boost::hana::is_empty

`#include <boost/hana/fwd/is_empty.hpp>`

Initial value:
= [](auto const& xs) {
return tag-dispatched;
}

Returns whether the iterable is empty.Given an `Iterable` `xs`, `is_empty` returns whether `xs` contains no more elements. In other words, it returns whether trying to extract the tail of `xs` would be an error. In the current version of the library, `is_empty` must return an `IntegralConstant` holding a value convertible to `bool`. This is because only compile-time `Iterable`s are supported right now.

## Example

// 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)
#include <boost/hana/assert.hpp>
#include <boost/hana/is_empty.hpp>
#include <boost/hana/not.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(hana::make_tuple(1, '2')));
BOOST_HANA_CONSTANT_CHECK( hana::is_empty(hana::make_tuple()));
int main() { }

constexpr auto boost::hana::lexicographical_compare

`#include <boost/hana/fwd/lexicographical_compare.hpp>`

Initial value:
= [](auto const& xs, auto const& ys, auto const& pred = hana::less) {
return tag-dispatched;
}
boost::hana::less
constexpr auto less
Returns a Logical representing whether x is less than y.
Definition: less.hpp:37

Short-circuiting lexicographical comparison of two `Iterable`s with an optional custom predicate, by default `hana::less`.Given two `Iterable`s `xs` and `ys` and a binary predicate `pred`, `lexicographical_compare` returns whether `xs` is to be considered less than `ys` in a lexicographical ordering. Specifically, let's denote the linearizations of `xs` and `ys` by `[x1, x2, ...]` and `[y1, y2, ...]`, respectively. If the first couple satisfying the predicate is of the form `xi, yi`, `lexicographical_compare` returns true. Otherwise, if the first couple to satisfy the predicate is of the form `yi, xi`, `lexicographical_compare` returns false. If no such couple can be found, `lexicographical_compare` returns whether `xs` has fewer elements than `ys`.

Note
  This algorithm will short-circuit as soon as it can determine that one sequence is lexicographically less than the other. Hence, it can be used to compare infinite sequences. However, for the procedure to terminate on infinite sequences, the predicate has to be satisfied at a finite index.

## Signature

Given two `Iterable`s `It1(T)` and `It2(T)` and a predicate \( pred : T \times T \to Bool \) (where `Bool` is some `Logical`), `lexicographical_compare` has the following signatures. For the variant with a provided predicate,

\[ \mathtt{lexicographical\_compare} : It1(T) \times It2(T) \times (T \times T \to Bool) \to Bool \]

for the variant without a custom predicate, `T` is required to be `Orderable`. The signature is then

\[ \mathtt{lexicographical\_compare} : It1(T) \times It2(T) \to Bool \]

Parameters

  xs,ys | Two `Iterable`s to compare lexicographically.
  pred | A binary function called as `pred(x, y)` and `pred(y, x)`, where `x` and `y` are elements of `xs` and `ys`, respectively. `pred` must return a `Logical` representing whether its first argument is to be considered as less than its second argument. Also note that `pred` must define a total ordering as defined by the `Orderable` concept. When `pred` is not provided, it defaults to `less`.

## Example

// 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)
#include <boost/hana/assert.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/less.hpp>
#include <boost/hana/lexicographical_compare.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
int main() {
// works with elements whose `less` does not return a Constant
{
constexpr auto xs = hana::make_tuple(1, 2, 3, 4);
constexpr auto ys = hana::make_tuple(1, 6, 3, 4);
static_assert(hana::lexicographical_compare(xs, ys), "");
}
// and with those that do
{
auto xs = hana::make_tuple(hana::int_c<1>, hana::int_c<2>, hana::int_c<3>);
auto ys = hana::make_tuple(hana::int_c<1>, hana::int_c<5>, hana::int_c<3>);
BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(xs, ys));
}
// it also accepts a custom predicate
{
auto xs = hana::make_tuple(hana::type_c<int>, hana::type_c<char>, hana::type_c<void*>);
auto ys = hana::make_tuple(hana::type_c<int>, hana::type_c<long>, hana::type_c<void*>);
BOOST_HANA_CONSTANT_CHECK(
hana::lexicographical_compare(xs, ys, [](auto t, auto u) {
return hana::sizeof_(t) < hana::sizeof_(u);
})
);
}
}

## Benchmarks