summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/test/_include
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/hana/test/_include')
-rw-r--r--src/boost/libs/hana/test/_include/auto/README.md44
-rw-r--r--src/boost/libs/hana/test/_include/auto/all_of.hpp120
-rw-r--r--src/boost/libs/hana/test/_include/auto/any_of.hpp173
-rw-r--r--src/boost/libs/hana/test/_include/auto/ap.hpp76
-rw-r--r--src/boost/libs/hana/test/_include/auto/at.hpp91
-rw-r--r--src/boost/libs/hana/test/_include/auto/cartesian_product.hpp234
-rw-r--r--src/boost/libs/hana/test/_include/auto/drop_back.hpp99
-rw-r--r--src/boost/libs/hana/test/_include/auto/drop_front.hpp160
-rw-r--r--src/boost/libs/hana/test/_include/auto/drop_while.hpp72
-rw-r--r--src/boost/libs/hana/test/_include/auto/for_each.hpp64
-rw-r--r--src/boost/libs/hana/test/_include/auto/group.hpp150
-rw-r--r--src/boost/libs/hana/test/_include/auto/index_if.hpp81
-rw-r--r--src/boost/libs/hana/test/_include/auto/insert.hpp84
-rw-r--r--src/boost/libs/hana/test/_include/auto/insert_range.hpp105
-rw-r--r--src/boost/libs/hana/test/_include/auto/intersperse.hpp54
-rw-r--r--src/boost/libs/hana/test/_include/auto/is_empty.hpp55
-rw-r--r--src/boost/libs/hana/test/_include/auto/length.hpp48
-rw-r--r--src/boost/libs/hana/test/_include/auto/lexicographical_compare.hpp109
-rw-r--r--src/boost/libs/hana/test/_include/auto/make.hpp41
-rw-r--r--src/boost/libs/hana/test/_include/auto/none_of.hpp90
-rw-r--r--src/boost/libs/hana/test/_include/auto/partition.hpp74
-rw-r--r--src/boost/libs/hana/test/_include/auto/permutations.hpp87
-rw-r--r--src/boost/libs/hana/test/_include/auto/remove_at.hpp130
-rw-r--r--src/boost/libs/hana/test/_include/auto/remove_range.hpp114
-rw-r--r--src/boost/libs/hana/test/_include/auto/reverse.hpp55
-rw-r--r--src/boost/libs/hana/test/_include/auto/scans.hpp216
-rw-r--r--src/boost/libs/hana/test/_include/auto/sequence.hpp13
-rw-r--r--src/boost/libs/hana/test/_include/auto/slice.hpp182
-rw-r--r--src/boost/libs/hana/test/_include/auto/sort.hpp111
-rw-r--r--src/boost/libs/hana/test/_include/auto/span.hpp84
-rw-r--r--src/boost/libs/hana/test/_include/auto/take_back.hpp82
-rw-r--r--src/boost/libs/hana/test/_include/auto/take_front.hpp77
-rw-r--r--src/boost/libs/hana/test/_include/auto/take_while.hpp68
-rw-r--r--src/boost/libs/hana/test/_include/auto/test_case.hpp13
-rw-r--r--src/boost/libs/hana/test/_include/auto/transform.hpp74
-rw-r--r--src/boost/libs/hana/test/_include/auto/unfolds.hpp170
-rw-r--r--src/boost/libs/hana/test/_include/auto/unique.hpp158
-rw-r--r--src/boost/libs/hana/test/_include/auto/zips.hpp342
-rw-r--r--src/boost/libs/hana/test/_include/laws/applicative.hpp196
-rw-r--r--src/boost/libs/hana/test/_include/laws/base.hpp369
-rw-r--r--src/boost/libs/hana/test/_include/laws/comonad.hpp53
-rw-r--r--src/boost/libs/hana/test/_include/laws/comparable.hpp167
-rw-r--r--src/boost/libs/hana/test/_include/laws/constant.hpp106
-rw-r--r--src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp99
-rw-r--r--src/boost/libs/hana/test/_include/laws/foldable.hpp1104
-rw-r--r--src/boost/libs/hana/test/_include/laws/functor.hpp250
-rw-r--r--src/boost/libs/hana/test/_include/laws/group.hpp93
-rw-r--r--src/boost/libs/hana/test/_include/laws/hashable.hpp60
-rw-r--r--src/boost/libs/hana/test/_include/laws/iterable.hpp195
-rw-r--r--src/boost/libs/hana/test/_include/laws/logical.hpp137
-rw-r--r--src/boost/libs/hana/test/_include/laws/monad.hpp222
-rw-r--r--src/boost/libs/hana/test/_include/laws/monad_plus.hpp616
-rw-r--r--src/boost/libs/hana/test/_include/laws/monoid.hpp86
-rw-r--r--src/boost/libs/hana/test/_include/laws/orderable.hpp182
-rw-r--r--src/boost/libs/hana/test/_include/laws/product.hpp46
-rw-r--r--src/boost/libs/hana/test/_include/laws/ring.hpp125
-rw-r--r--src/boost/libs/hana/test/_include/laws/searchable.hpp611
-rw-r--r--src/boost/libs/hana/test/_include/laws/sequence.hpp133
-rw-r--r--src/boost/libs/hana/test/_include/laws/templates/seq.hpp132
-rw-r--r--src/boost/libs/hana/test/_include/support/cnumeric.hpp66
-rw-r--r--src/boost/libs/hana/test/_include/support/constexpr_move_only.hpp41
-rw-r--r--src/boost/libs/hana/test/_include/support/counter.hpp56
-rw-r--r--src/boost/libs/hana/test/_include/support/equivalence_class.hpp34
-rw-r--r--src/boost/libs/hana/test/_include/support/identity.hpp159
-rw-r--r--src/boost/libs/hana/test/_include/support/minimal_product.hpp61
-rw-r--r--src/boost/libs/hana/test/_include/support/numeric.hpp175
-rw-r--r--src/boost/libs/hana/test/_include/support/seq.hpp122
-rw-r--r--src/boost/libs/hana/test/_include/support/tracked.hpp120
-rw-r--r--src/boost/libs/hana/test/_include/support/tracked_move_only.hpp45
69 files changed, 9861 insertions, 0 deletions
diff --git a/src/boost/libs/hana/test/_include/auto/README.md b/src/boost/libs/hana/test/_include/auto/README.md
new file mode 100644
index 000000000..082906c28
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/README.md
@@ -0,0 +1,44 @@
+The headers in this directory provide facilities for automatic unit testing.
+Basically, each header defines unit tests for an algorithm or a set of related
+algorithms. To get the tests for these algorithms, simply include the header
+at global scope. However, before including the header, you must define the
+following macros:
+
+ `MAKE_TUPLE(...)`
+ Must expand to a sequence holding `__VA_ARGS__`. A valid definition
+ would be `hana::make_tuple(__VA_ARGS__)`.
+
+ `TUPLE_TYPE(...)`
+ Must expand to the type of a sequence holding objects of type `__VA_ARGS__`.
+ A valid definition would be `hana::tuple<__VA_ARGS__>`.
+
+ `TUPLE_TAG`
+ Must expand to the tag of the sequence. A valid definition would
+ be `hana::tuple_tag`.
+
+
+The following macros may or may not be defined:
+
+ `MAKE_TUPLE_NO_CONSTEXPR`
+ Must be defined if the `MAKE_TUPLE` macro can't be used inside a
+ constant expression. Otherwise, `MAKE_TUPLE` is assumed to be able
+ to construct a `constexpr` container.
+
+The following directories contain automatic unit tests, and the following is
+sufficient when adding a new automatic unit test (in a file `${FILE}`):
+
+```sh
+DIRECTORIES=$(find test -type d -name auto | grep -v test/_include/auto)
+for d in ${DIRECTORIES}; do
+ cat > ${d}/${FILE}.cpp <<EOF
+// 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 "_specs.hpp"
+#include <auto/${FILE}.hpp>
+
+int main() { }
+EOF
+done
+```
diff --git a/src/boost/libs/hana/test/_include/auto/all_of.hpp b/src/boost/libs/hana/test/_include/auto/all_of.hpp
new file mode 100644
index 000000000..b1bdc1125
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/all_of.hpp
@@ -0,0 +1,120 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_ALL_OF_HPP
+#define BOOST_HANA_TEST_AUTO_ALL_OF_HPP
+
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/not.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_all_of{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(),
+ [](auto) { return hana::false_c; }
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<999>{}, ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<999>{}, ct_eq<0>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<999>{}, ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::all_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}, ct_eq<999>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+
+ // Make sure `all_of` short-circuits with runtime predicates
+ // See http://stackoverflow.com/q/42012512/627587
+ {
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{});
+ hana::all_of(tuple, [&](auto) { ++counter; return false; });
+ BOOST_HANA_RUNTIME_CHECK(counter == 1);
+ }
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<0>{}, ct_eq<999>{}, ct_eq<0>{});
+ hana::all_of(tuple, [&](auto x) -> bool {
+ ++counter;
+ return hana::equal(x, ct_eq<0>{});
+ });
+ BOOST_HANA_RUNTIME_CHECK(counter == 2);
+ }
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_ALL_OF_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/any_of.hpp b/src/boost/libs/hana/test/_include/auto/any_of.hpp
new file mode 100644
index 000000000..400b5a3b1
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/any_of.hpp
@@ -0,0 +1,173 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_ANY_OF_HPP
+#define BOOST_HANA_TEST_AUTO_ANY_OF_HPP
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/not.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_any_of{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(),
+ [](auto) { return hana::true_c; }
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::equal.to(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::equal.to(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::equal.to(ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::equal.to(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::equal.to(ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::equal.to(ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ [](auto) { return hana::false_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ [](auto) { return hana::true_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<999>{})
+ )));
+
+ // Make sure `any_of` short-circuits with runtime predicates
+ // See http://stackoverflow.com/q/42012512/627587
+ {
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{});
+ hana::any_of(tuple, [&](auto) { ++counter; return true; });
+ BOOST_HANA_RUNTIME_CHECK(counter == 1);
+ }
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{});
+ hana::any_of(tuple, [&](auto x) -> bool {
+ ++counter;
+ return hana::equal(x, ct_eq<1>{});
+ });
+ BOOST_HANA_RUNTIME_CHECK(counter == 2);
+ }
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_ANY_OF_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/ap.hpp b/src/boost/libs/hana/test/_include/auto/ap.hpp
new file mode 100644
index 000000000..7fe0fc5be
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/ap.hpp
@@ -0,0 +1,76 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_AP_HPP
+#define BOOST_HANA_TEST_AUTO_AP_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/ap.hpp>
+#include <boost/hana/equal.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_ap{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ hana::test::_injection<0> f{};
+ hana::test::_injection<1> g{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f), MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f, g), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f, g), MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), g(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f, g), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}), g(ct_eq<0>{}), g(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(MAKE_TUPLE(f, g), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}),
+ g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_AP_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/at.hpp b/src/boost/libs/hana/test/_include/auto/at.hpp
new file mode 100644
index 000000000..66574a361
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/at.hpp
@@ -0,0 +1,91 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_AT_HPP
+#define BOOST_HANA_TEST_AUTO_AT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/tracked.hpp>
+
+
+namespace _test_at_detail { template <int> struct invalid { }; }
+
+
+TestCase test_at{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ using _test_at_detail::invalid;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ ct_eq<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(ct_eq<0>{}, invalid<1>{}), hana::size_c<0>),
+ ct_eq<0>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(invalid<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ ct_eq<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(invalid<0>{}, ct_eq<1>{}, invalid<2>{}), hana::size_c<1>),
+ ct_eq<1>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(invalid<0>{}, invalid<1>{}, ct_eq<2>{}), hana::size_c<2>),
+ ct_eq<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::at(MAKE_TUPLE(invalid<0>{}, invalid<1>{}, ct_eq<2>{}, invalid<3>{}), hana::size_c<2>),
+ ct_eq<2>{}
+ ));
+
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1), hana::size_c<0>),
+ 1
+ ), "");
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1, '2'), hana::size_c<0>),
+ 1
+ ), "");
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1, '2', 3.3), hana::size_c<0>),
+ 1
+ ), "");
+
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1, '2'), hana::size_c<1>),
+ '2'
+ ), "");
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1, '2', 3.3), hana::size_c<1>),
+ '2'
+ ), "");
+
+ static_assert(hana::equal(
+ hana::at(MAKE_TUPLE(1, '2', 3.3), hana::size_c<2>),
+ 3.3
+ ), "");
+#endif
+
+ // make sure we can use non-pods on both sides
+ {
+ // store the result to make sure `at` is executed.
+ auto result = hana::at(MAKE_TUPLE(Tracked{0}, ct_eq<1>{}, Tracked{1}), hana::size_c<1>);;
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(result, ct_eq<1>{}));
+ }
+
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_AT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/cartesian_product.hpp b/src/boost/libs/hana/test/_include/auto/cartesian_product.hpp
new file mode 100644
index 000000000..8aecf3649
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/cartesian_product.hpp
@@ -0,0 +1,234 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_CARTESIAN_PRODUCT_HPP
+#define BOOST_HANA_TEST_AUTO_CARTESIAN_PRODUCT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/cartesian_product.hpp>
+#include <boost/hana/equal.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_cartesian_product{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ // 0 lists
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+
+ // 1 list
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE()
+ )),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<3>{})
+ )
+ ));
+
+ // 2 lists
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(),
+ MAKE_TUPLE()
+ )),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}),
+ MAKE_TUPLE()
+ )),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}),
+ MAKE_TUPLE(ct_eq<10>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<01>{}),
+ MAKE_TUPLE(ct_eq<10>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<01>{}, ct_eq<10>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}),
+ MAKE_TUPLE(ct_eq<10>{}, ct_eq<11>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<11>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<01>{}),
+ MAKE_TUPLE(ct_eq<10>{}, ct_eq<11>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<11>{}),
+ MAKE_TUPLE(ct_eq<01>{}, ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<01>{}, ct_eq<11>{})
+ )
+ ));
+
+ // misc
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}),
+ MAKE_TUPLE(ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<20>{}),
+ MAKE_TUPLE(ct_eq<30>{}, ct_eq<31>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<20>{}, ct_eq<30>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<20>{}, ct_eq<31>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}),
+ MAKE_TUPLE(ct_eq<10>{}),
+ MAKE_TUPLE(ct_eq<20>{}, ct_eq<21>{}),
+ MAKE_TUPLE(ct_eq<30>{}, ct_eq<31>{})
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<20>{}, ct_eq<30>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<20>{}, ct_eq<31>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<21>{}, ct_eq<30>{}),
+ MAKE_TUPLE(ct_eq<00>{}, ct_eq<10>{}, ct_eq<21>{}, ct_eq<31>{})
+ )
+ ));
+
+
+ // cartesian_product in a constexpr context
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ static_assert(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(1),
+ MAKE_TUPLE('a', 'b')
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(1, 'a'),
+ MAKE_TUPLE(1, 'b')
+ )
+ ), "");
+
+ static_assert(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(1, 2),
+ MAKE_TUPLE('a')
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(1, 'a'),
+ MAKE_TUPLE(2, 'a')
+ )
+ ), "");
+
+ static_assert(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(1, 2),
+ MAKE_TUPLE('a', 'b')
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(1, 'a'),
+ MAKE_TUPLE(1, 'b'),
+ MAKE_TUPLE(2, 'a'),
+ MAKE_TUPLE(2, 'b')
+ )
+ ), "");
+
+ static_assert(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(1),
+ MAKE_TUPLE('a'),
+ MAKE_TUPLE(1.f),
+ MAKE_TUPLE(1l, 2l)
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(1, 'a', 1.f, 1l),
+ MAKE_TUPLE(1, 'a', 1.f, 2l)
+ )
+ ), "");
+
+ static_assert(hana::equal(
+ hana::cartesian_product(MAKE_TUPLE(
+ MAKE_TUPLE(1),
+ MAKE_TUPLE('a'),
+ MAKE_TUPLE(1.f),
+ MAKE_TUPLE(1l, 2l),
+ MAKE_TUPLE(nullptr)
+ )),
+ MAKE_TUPLE(
+ MAKE_TUPLE(1, 'a', 1.f, 1l, nullptr),
+ MAKE_TUPLE(1, 'a', 1.f, 2l, nullptr)
+ )
+ ), "");
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_CARTESIAN_PRODUCT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/drop_back.hpp b/src/boost/libs/hana/test/_include/auto/drop_back.hpp
new file mode 100644
index 000000000..e3ea42e0c
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/drop_back.hpp
@@ -0,0 +1,99 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_DROP_BACK_HPP
+#define BOOST_HANA_TEST_AUTO_DROP_BACK_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/drop_back.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_drop_back{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<3>),
+ MAKE_TUPLE()
+ ));
+
+ // make sure hana::drop_back(xs) == hana::drop_back(xs, hana::size_c<1>)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE()),
+ hana::drop_back(MAKE_TUPLE(), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{})),
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{})),
+ hana::drop_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}), hana::size_c<1>)
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_DROP_BACK_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/drop_front.hpp b/src/boost/libs/hana/test/_include/auto/drop_front.hpp
new file mode 100644
index 000000000..05988ace2
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/drop_front.hpp
@@ -0,0 +1,160 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_DROP_FRONT_HPP
+#define BOOST_HANA_TEST_AUTO_DROP_FRONT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/drop_front_exactly.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_drop_front{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<3>),
+ MAKE_TUPLE()
+ ));
+
+ // make sure hana::drop_front(xs) == hana::drop_front(xs, size_c<1>)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE()),
+ hana::drop_front(MAKE_TUPLE(), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{})),
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{})),
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+}};
+
+TestCase test_drop_front_exactly{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_front_exactly(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{},
+ ct_eq<4>{}, ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}), hana::size_c<4>),
+ MAKE_TUPLE(ct_eq<4>{}, ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{})
+ ));
+
+ // make sure drop_front_exactly(xs) == drop_front_exactly(xs, size_c<1>)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{})),
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{})),
+ hana::drop_front_exactly(MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}), hana::size_c<1>)
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_DROP_FRONT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/drop_while.hpp b/src/boost/libs/hana/test/_include/auto/drop_while.hpp
new file mode 100644
index 000000000..054d79be0
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/drop_while.hpp
@@ -0,0 +1,72 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_DROP_WHILE_HPP
+#define BOOST_HANA_TEST_AUTO_DROP_WHILE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/drop_while.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/not_equal.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_drop_while{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(), hana::id),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::true_c), hana::id),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::false_c), hana::id),
+ MAKE_TUPLE(hana::false_c)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::true_c, hana::true_c), hana::id),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::true_c, hana::false_c), hana::id),
+ MAKE_TUPLE(hana::false_c)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::false_c, hana::true_c), hana::id),
+ MAKE_TUPLE(hana::false_c, hana::true_c)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(hana::false_c, hana::false_c), hana::id),
+ MAKE_TUPLE(hana::false_c, hana::false_c)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::not_equal.to(ct_eq<99>{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::not_equal.to(ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::not_equal.to(ct_eq<3>{})),
+ MAKE_TUPLE(ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::drop_while(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::not_equal.to(ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_DROP_WHILE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/for_each.hpp b/src/boost/libs/hana/test/_include/auto/for_each.hpp
new file mode 100644
index 000000000..4e36e9853
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/for_each.hpp
@@ -0,0 +1,64 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_FOR_EACH_HPP
+#define BOOST_HANA_TEST_AUTO_FOR_EACH_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/for_each.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+#include <vector>
+
+
+TestCase test_for_each{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ // Make sure the function is applied in left-to-right order.
+ {
+ auto check = [](auto ...xs) {
+ std::vector<int> seen{};
+ hana::for_each(MAKE_TUPLE(xs...), [&](int x) {
+ seen.push_back(x);
+ });
+ BOOST_HANA_RUNTIME_CHECK(seen == std::vector<int>{xs...});
+ };
+
+ check();
+ check(0);
+ check(0, 1);
+ check(0, 1, 2);
+ check(0, 1, 2, 3);
+ check(0, 1, 2, 3, 4);
+ }
+
+ // Make sure the function is never called when the sequence is empty.
+ {
+ struct undefined { };
+ hana::for_each(MAKE_TUPLE(), undefined{});
+ }
+
+ // Make sure it works with heterogeneous sequences.
+ {
+ hana::for_each(MAKE_TUPLE(ct_eq<0>{}), [](auto) { });
+ hana::for_each(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), [](auto) { });
+ hana::for_each(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), [](auto) { });
+ hana::for_each(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), [](auto) { });
+ }
+
+ // Make sure for_each is constexpr when used with a constexpr function
+ // and constexpr arguments. This used not to be the case.
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ {
+ struct f { constexpr void operator()(int) const { } };
+ constexpr int i = (hana::for_each(MAKE_TUPLE(1, 2, 3), f{}), 0);
+ (void)i;
+ }
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_FOR_EACH_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/group.hpp b/src/boost/libs/hana/test/_include/auto/group.hpp
new file mode 100644
index 000000000..1802ebd33
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/group.hpp
@@ -0,0 +1,150 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_GROUP_HPP
+#define BOOST_HANA_TEST_AUTO_GROUP_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/group.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/equivalence_class.hpp>
+
+
+TestCase test_group{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+
+ // Test without a custom predicate
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<0>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{}, ct_eq<0>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<1>{}, ct_eq<1>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<1>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<2>{}, ct_eq<2>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<2>{}, ct_eq<2>{}))
+ ));
+ }
+
+ // Test with a custom predicate
+ {
+ auto a = [](auto z) { return ::equivalence_class(ct_eq<999>{}, z); };
+ auto b = [](auto z) { return ::equivalence_class(ct_eq<888>{}, z); };
+
+ auto pred = [](auto x, auto y) {
+ return hana::equal(x.unwrap, y.unwrap);
+ };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(a(ct_eq<0>{})), pred),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{})))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})), pred),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), a(ct_eq<1>{})), pred),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})),
+ MAKE_TUPLE(a(ct_eq<1>{})))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), a(ct_eq<1>{}), b(ct_eq<1>{})), pred),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})),
+ MAKE_TUPLE(a(ct_eq<1>{}), b(ct_eq<1>{})))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), a(ct_eq<1>{}), b(ct_eq<1>{}), b(ct_eq<0>{})), pred),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})),
+ MAKE_TUPLE(a(ct_eq<1>{}), b(ct_eq<1>{})),
+ MAKE_TUPLE(b(ct_eq<0>{})))
+ ));
+
+ // Test group.by syntactic sugar
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group.by(pred, MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), a(ct_eq<1>{}), b(ct_eq<1>{}), b(ct_eq<0>{}))),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})),
+ MAKE_TUPLE(a(ct_eq<1>{}), b(ct_eq<1>{})),
+ MAKE_TUPLE(b(ct_eq<0>{})))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::group.by(pred)(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), a(ct_eq<1>{}), b(ct_eq<1>{}), b(ct_eq<0>{}))),
+ MAKE_TUPLE(
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})),
+ MAKE_TUPLE(a(ct_eq<1>{}), b(ct_eq<1>{})),
+ MAKE_TUPLE(b(ct_eq<0>{})))
+ ));
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_GROUP_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/index_if.hpp b/src/boost/libs/hana/test/_include/auto/index_if.hpp
new file mode 100644
index 000000000..af7c86bbc
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/index_if.hpp
@@ -0,0 +1,81 @@
+// Copyright Louis Dionne 2013-2017
+// Copyright Jason Rice 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_INDEX_IF_HPP
+#define BOOST_HANA_TEST_AUTO_INDEX_IF_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/index_if.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/tracked.hpp>
+
+
+namespace _test_index_if_detail { template <int> struct invalid { }; }
+
+
+TestCase test_index_if{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ using _test_index_if_detail::invalid;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(), hana::equal.to(ct_eq<0>{})),
+ hana::nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}), hana::equal.to(ct_eq<0>{})),
+ hana::just(hana::size_c<0>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}), hana::equal.to(ct_eq<42>{})),
+ hana::nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(ct_eq<0>{})),
+ hana::just(hana::size_c<0>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(ct_eq<1>{})),
+ hana::just(hana::size_c<1>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(ct_eq<2>{})),
+ hana::just(hana::size_c<2>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::index_if(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(ct_eq<42>{})),
+ hana::nothing
+ ));
+
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ auto type_equal = [](auto type) { return [=](auto&& value) {
+ return hana::equal(hana::typeid_(value), type);
+ };};
+
+ static_assert(decltype(hana::equal(
+ hana::index_if(MAKE_TUPLE(1, '2', 3.3), type_equal(hana::type_c<int>)),
+ hana::just(hana::size_c<0>)
+ )){}, "");
+ static_assert(decltype(hana::equal(
+ hana::index_if(MAKE_TUPLE(1, '2', 3.3), type_equal(hana::type_c<char>)),
+ hana::just(hana::size_c<1>)
+ )){}, "");
+ static_assert(decltype(hana::equal(
+ hana::index_if(MAKE_TUPLE(1, '2', 3.3), type_equal(hana::type_c<double>)),
+ hana::just(hana::size_c<2>)
+ )){}, "");
+ static_assert(decltype(hana::equal(
+ hana::index_if(MAKE_TUPLE(1, '2', 3.3), type_equal(hana::type_c<invalid<42>>)),
+ hana::nothing
+ )){}, "");
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_INDEX_IF_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/insert.hpp b/src/boost/libs/hana/test/_include/auto/insert.hpp
new file mode 100644
index 000000000..c9715452a
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/insert.hpp
@@ -0,0 +1,84 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_INSERT_HPP
+#define BOOST_HANA_TEST_AUTO_INSERT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/insert.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_insert{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto z = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>, z),
+ MAKE_TUPLE(z, ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>, z),
+ MAKE_TUPLE(ct_eq<0>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>, z),
+ MAKE_TUPLE(z, ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>, z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<0>, z),
+ MAKE_TUPLE(z, ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<1>, z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<2>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, z, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::size_c<3>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<0>, z),
+ MAKE_TUPLE(z, ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<1>, z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<2>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, z, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<3>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, z, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<4>, z),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, z)
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_INSERT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/insert_range.hpp b/src/boost/libs/hana/test/_include/auto/insert_range.hpp
new file mode 100644
index 000000000..ac929d7ed
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/insert_range.hpp
@@ -0,0 +1,105 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_INSERT_RANGE_HPP
+#define BOOST_HANA_TEST_AUTO_INSERT_RANGE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/insert_range.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/seq.hpp>
+
+
+TestCase test_insert_range{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto foldable = ::seq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}),
+ hana::size_c<0>,
+ foldable()),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}),
+ hana::size_c<0>,
+ foldable(ct_eq<-1>{})),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}),
+ hana::size_c<0>,
+ foldable(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}),
+ hana::size_c<0>,
+ foldable(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<-3>{})),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<-3>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<0>,
+ foldable()),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<0>,
+ foldable(ct_eq<-1>{})),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<0>,
+ foldable(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<1>,
+ foldable()),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<1>,
+ foldable(ct_eq<-1>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<-1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<1>,
+ foldable(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::insert_range(
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<2>,
+ foldable(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_INSERT_RANGE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/intersperse.hpp b/src/boost/libs/hana/test/_include/auto/intersperse.hpp
new file mode 100644
index 000000000..83e7e8148
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/intersperse.hpp
@@ -0,0 +1,54 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_INTERSPERSE_HPP
+#define BOOST_HANA_TEST_AUTO_INTERSPERSE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/intersperse.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_intersperse{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+
+ auto z = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}), undefined{}),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, z, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, z, ct_eq<2>{}, z, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, z, ct_eq<2>{}, z, ct_eq<3>{}, z, ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::intersperse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}), z),
+ MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<1>{}, z, ct_eq<2>{}, z, ct_eq<3>{}, z, ct_eq<4>{}, z, ct_eq<5>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_INTERSPERSE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/is_empty.hpp b/src/boost/libs/hana/test/_include/auto/is_empty.hpp
new file mode 100644
index 000000000..99ae879dd
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/is_empty.hpp
@@ -0,0 +1,55 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_IS_EMPTY_HPP
+#define BOOST_HANA_TEST_AUTO_IS_EMPTY_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/not.hpp>
+
+#include "test_case.hpp"
+
+
+namespace _test_is_empty_detail { template <int i> struct undefined { }; }
+
+TestCase test_is_empty{[]{
+ namespace hana = boost::hana;
+ using _test_is_empty_detail::undefined;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::is_empty(
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(
+ MAKE_TUPLE(undefined<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(
+ MAKE_TUPLE(undefined<0>{}, undefined<1>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(
+ MAKE_TUPLE(undefined<0>{}, undefined<1>{}, undefined<2>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(
+ MAKE_TUPLE(undefined<0>{}, undefined<1>{}, undefined<2>{}, undefined<3>{})
+ )));
+
+ // Check with a runtime value
+ {
+ int i = 3; // <- runtime value
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(MAKE_TUPLE(i))));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(MAKE_TUPLE(i, i))));
+ }
+
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ static_assert(hana::is_empty(MAKE_TUPLE()), "");
+ static_assert(hana::not_(hana::is_empty(MAKE_TUPLE(undefined<0>{}))), "");
+ static_assert(hana::not_(hana::is_empty(MAKE_TUPLE(undefined<0>{}, undefined<1>{}))), "");
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_IS_EMPTY_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/length.hpp b/src/boost/libs/hana/test/_include/auto/length.hpp
new file mode 100644
index 000000000..25f75dc4d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/length.hpp
@@ -0,0 +1,48 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_LENGTH_HPP
+#define BOOST_HANA_TEST_AUTO_LENGTH_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+
+#include "test_case.hpp"
+
+
+namespace _test_length_detail { template <int> struct undefined { }; }
+
+TestCase test_length{[]{
+ namespace hana = boost::hana;
+ using _test_length_detail::undefined;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::length(MAKE_TUPLE()),
+ hana::size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::length(MAKE_TUPLE(undefined<1>{})),
+ hana::size_c<1>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::length(MAKE_TUPLE(undefined<1>{}, undefined<2>{})),
+ hana::size_c<2>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::length(MAKE_TUPLE(undefined<1>{}, undefined<2>{}, undefined<3>{})),
+ hana::size_c<3>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::length(MAKE_TUPLE(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, undefined<5>{}, undefined<6>{})),
+ hana::size_c<6>
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_LENGTH_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/lexicographical_compare.hpp b/src/boost/libs/hana/test/_include/auto/lexicographical_compare.hpp
new file mode 100644
index 000000000..83870d561
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/lexicographical_compare.hpp
@@ -0,0 +1,109 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_LEXICOGRAPHICAL_COMPARE_HPP
+#define BOOST_HANA_TEST_AUTO_LEXICOGRAPHICAL_COMPARE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/lexicographical_compare.hpp>
+#include <boost/hana/not.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_lexicographical_compare{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_ord;
+
+ struct undefined { };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(),
+ MAKE_TUPLE()
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(),
+ MAKE_TUPLE(undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(undefined{}),
+ MAKE_TUPLE()
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}),
+ MAKE_TUPLE(ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}),
+ MAKE_TUPLE(ct_ord<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<1>{}),
+ MAKE_TUPLE(ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, undefined{}),
+ MAKE_TUPLE(ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}),
+ MAKE_TUPLE(ct_ord<0>{}, undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<0>{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<3>{}, undefined{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<3>{}, undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<3>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::lexicographical_compare(
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<3>{}),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, undefined{})
+ )));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_LEXICOGRAPHICAL_COMPARE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/make.hpp b/src/boost/libs/hana/test/_include/auto/make.hpp
new file mode 100644
index 000000000..83536edfd
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/make.hpp
@@ -0,0 +1,41 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_MAKE_HPP
+#define BOOST_HANA_TEST_AUTO_MAKE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/equal.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_make{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ MAKE_TUPLE(),
+ hana::make<TUPLE_TAG>()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::make<TUPLE_TAG>(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::make<TUPLE_TAG>(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::make<TUPLE_TAG>(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_MAKE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/none_of.hpp b/src/boost/libs/hana/test/_include/auto/none_of.hpp
new file mode 100644
index 000000000..7e1dff2d8
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/none_of.hpp
@@ -0,0 +1,90 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_NONE_OF_HPP
+#define BOOST_HANA_TEST_AUTO_NONE_OF_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/none_of.hpp>
+#include <boost/hana/not.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_none_of{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::none_of(
+ MAKE_TUPLE(),
+ [](auto) { return hana::false_c; }
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::true_c; }
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ [](auto) { return hana::false_c; }
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}),
+ hana::equal.to(ct_eq<999>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<1>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<2>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<3>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<4>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::none_of(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::equal.to(ct_eq<999>{})
+ ));
+
+ // Make sure `none_of` short-circuits with runtime predicates
+ // See http://stackoverflow.com/q/42012512/627587
+ {
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{});
+ hana::none_of(tuple, [&](auto) { ++counter; return true; });
+ BOOST_HANA_RUNTIME_CHECK(counter == 1);
+ }
+ {
+ int counter = 0;
+ auto tuple = MAKE_TUPLE(ct_eq<999>{}, ct_eq<0>{}, ct_eq<999>{});
+ hana::none_of(tuple, [&](auto x) -> bool {
+ ++counter;
+ return hana::equal(x, ct_eq<0>{});
+ });
+ BOOST_HANA_RUNTIME_CHECK(counter == 2);
+ }
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_NONE_OF_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/partition.hpp b/src/boost/libs/hana/test/_include/auto/partition.hpp
new file mode 100644
index 000000000..d1fa7212e
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/partition.hpp
@@ -0,0 +1,74 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_PARTITION_HPP
+#define BOOST_HANA_TEST_AUTO_PARTITION_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/partition.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/minimal_product.hpp>
+
+
+TestCase test_partition{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+
+ auto pair = ::minimal_product;
+ auto pred = hana::in ^ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<-3>{}, ct_eq<-4>{}, ct_eq<-5>{});
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(), undefined{}),
+ pair(MAKE_TUPLE(), MAKE_TUPLE())
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<0>{}), pred),
+ pair(MAKE_TUPLE(),
+ MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), pred),
+ pair(MAKE_TUPLE(),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<-1>{}), pred),
+ pair(MAKE_TUPLE(ct_eq<-1>{}),
+ MAKE_TUPLE())
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<0>{}, ct_eq<2>{}), pred),
+ pair(MAKE_TUPLE(ct_eq<-1>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<0>{}, ct_eq<-3>{}, ct_eq<2>{}, ct_eq<-5>{}, ct_eq<6>{}), pred),
+ pair(MAKE_TUPLE(ct_eq<-3>{}, ct_eq<-5>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<6>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<2>{}, ct_eq<-3>{}, ct_eq<0>{}, ct_eq<-3>{}, ct_eq<4>{}), pred),
+ pair(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-3>{}, ct_eq<-3>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<0>{}, ct_eq<4>{}))
+ ));
+
+ // partition.by
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition.by(pred, MAKE_TUPLE(ct_eq<-1>{}, ct_eq<0>{}, ct_eq<2>{})),
+ hana::partition(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<0>{}, ct_eq<2>{}), pred)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::partition.by(pred)(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<0>{}, ct_eq<2>{})),
+ hana::partition(MAKE_TUPLE(ct_eq<-1>{}, ct_eq<0>{}, ct_eq<2>{}), pred)
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_PARTITION_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/permutations.hpp b/src/boost/libs/hana/test/_include/auto/permutations.hpp
new file mode 100644
index 000000000..d854103ac
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/permutations.hpp
@@ -0,0 +1,87 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_PERMUTATIONS_HPP
+#define BOOST_HANA_TEST_AUTO_PERMUTATIONS_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/permutations.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_permutations{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto is_permutation = [](auto xs, auto ys) {
+ return hana::and_(hana::is_subset(xs, ys), hana::is_subset(ys, xs));
+ };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::permutations(MAKE_TUPLE()),
+ MAKE_TUPLE(MAKE_TUPLE())
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::permutations(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_permutation(
+ hana::permutations(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_permutation(
+ hana::permutations(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<0>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{})
+ )
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_permutation(
+ hana::permutations(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})),
+ MAKE_TUPLE(
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<3>{}, ct_eq<1>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<3>{}, ct_eq<2>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{}, ct_eq<2>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{}, ct_eq<3>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<0>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<3>{}, ct_eq<0>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<3>{}, ct_eq<2>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<0>{}, ct_eq<1>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<0>{}, ct_eq<3>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<3>{}, ct_eq<0>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<3>{}, ct_eq<1>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<1>{}, ct_eq<0>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<2>{}, ct_eq<0>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{})
+ )
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_PERMUTATIONS_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/remove_at.hpp b/src/boost/libs/hana/test/_include/auto/remove_at.hpp
new file mode 100644
index 000000000..296b989e8
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/remove_at.hpp
@@ -0,0 +1,130 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_REMOVE_AT_HPP
+#define BOOST_HANA_TEST_AUTO_REMOVE_AT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/remove_at.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_remove_at{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}),
+ hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ hana::size_c<4>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+
+ // remove_at_c
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<0>(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<0>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<1>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<0>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<1>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_at_c<2>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_REMOVE_AT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/remove_range.hpp b/src/boost/libs/hana/test/_include/auto/remove_range.hpp
new file mode 100644
index 000000000..51bbf9133
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/remove_range.hpp
@@ -0,0 +1,114 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_REMOVE_RANGE_HPP
+#define BOOST_HANA_TEST_AUTO_REMOVE_RANGE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/remove_range.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_remove_range{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(), hana::size_c<0>, hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(), hana::size_c<1>, hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(), hana::size_c<2>, hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>, hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>, hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>, hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<2>, hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>, hana::size_c<0>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>, hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>, hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>, hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>, hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::size_c<9999>, hana::size_c<9999>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<0>, hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::size_c<1>, hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<0>, hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::size_c<2>, hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<3>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{},
+ ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{}),
+ hana::size_c<4>, hana::size_c<7>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{})
+ ));
+
+ // remove_range_c
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::remove_range_c<4, 7>(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{},
+ ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_REMOVE_RANGE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/reverse.hpp b/src/boost/libs/hana/test/_include/auto/reverse.hpp
new file mode 100644
index 000000000..c0c2000c5
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/reverse.hpp
@@ -0,0 +1,55 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_REVERSE_HPP
+#define BOOST_HANA_TEST_AUTO_REVERSE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/reverse.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_reverse{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ using hana::test::cx_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::reverse(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::reverse(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::reverse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::reverse(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{})
+ ));
+
+
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ static_assert(hana::equal(
+ hana::reverse(MAKE_TUPLE(cx_eq<1>{})),
+ MAKE_TUPLE(cx_eq<1>{})
+ ), "");
+ static_assert(hana::equal(
+ hana::reverse(MAKE_TUPLE(cx_eq<1>{}, cx_eq<2>{})),
+ MAKE_TUPLE(cx_eq<2>{}, cx_eq<1>{})
+ ), "");
+ static_assert(hana::equal(
+ hana::reverse(MAKE_TUPLE(cx_eq<1>{}, cx_eq<2>{}, cx_eq<3>{})),
+ MAKE_TUPLE(cx_eq<3>{}, cx_eq<2>{}, cx_eq<1>{})
+ ), "");
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_REVERSE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/scans.hpp b/src/boost/libs/hana/test/_include/auto/scans.hpp
new file mode 100644
index 000000000..5c5c0dd6a
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/scans.hpp
@@ -0,0 +1,216 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_SCANS_HPP
+#define BOOST_HANA_TEST_AUTO_SCANS_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/scan_left.hpp>
+#include <boost/hana/scan_right.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_scan_left{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+ hana::test::_injection<0> f{};
+
+ // Without initial state
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}), undefined{}),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), f),
+ MAKE_TUPLE(ct_eq<0>{}, f(ct_eq<0>{}, ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), f),
+ MAKE_TUPLE(
+ ct_eq<0>{},
+ f(ct_eq<0>{}, ct_eq<1>{}),
+ f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{})
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), f),
+ MAKE_TUPLE(
+ ct_eq<0>{},
+ f(ct_eq<0>{}, ct_eq<1>{}),
+ f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{}),
+ f(f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{})
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), f),
+ MAKE_TUPLE(
+ ct_eq<0>{},
+ f(ct_eq<0>{}, ct_eq<1>{}),
+ f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{}),
+ f(f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{}),
+ f(f(f(f(ct_eq<0>{}, ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{}), ct_eq<4>{})
+ )
+ ));
+
+ // With initial state
+ auto s = ct_eq<999>{};
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(), s, undefined{}),
+ MAKE_TUPLE(s)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}), s, f),
+ MAKE_TUPLE(s, f(s, ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), s, f),
+ MAKE_TUPLE(s, f(s, ct_eq<0>{}), f(f(s, ct_eq<0>{}), ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), s, f),
+ MAKE_TUPLE(
+ s,
+ f(s, ct_eq<0>{}),
+ f(f(s, ct_eq<0>{}), ct_eq<1>{}),
+ f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{})
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), s, f),
+ MAKE_TUPLE(
+ s,
+ f(s, ct_eq<0>{}),
+ f(f(s, ct_eq<0>{}), ct_eq<1>{}),
+ f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{}),
+ f(f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{})
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_left(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), s, f),
+ MAKE_TUPLE(
+ s,
+ f(s, ct_eq<0>{}),
+ f(f(s, ct_eq<0>{}), ct_eq<1>{}),
+ f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{}),
+ f(f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{}),
+ f(f(f(f(f(s, ct_eq<0>{}), ct_eq<1>{}), ct_eq<2>{}), ct_eq<3>{}), ct_eq<4>{})
+ )
+ ));
+}};
+
+
+TestCase test_scan_right{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+ hana::test::_injection<0> f{};
+
+ // Without initial state
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}), undefined{}),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, ct_eq<1>{}),
+ ct_eq<1>{}
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, ct_eq<2>{})),
+ f(ct_eq<1>{}, ct_eq<2>{}),
+ ct_eq<2>{}
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, f(ct_eq<2>{}, ct_eq<3>{}))),
+ f(ct_eq<1>{}, f(ct_eq<2>{}, ct_eq<3>{})),
+ f(ct_eq<2>{}, ct_eq<3>{}),
+ ct_eq<3>{}
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, ct_eq<4>{})))),
+ f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, ct_eq<4>{}))),
+ f(ct_eq<2>{}, f(ct_eq<3>{}, ct_eq<4>{})),
+ f(ct_eq<3>{}, ct_eq<4>{}),
+ ct_eq<4>{}
+ )
+ ));
+
+ // With initial state
+ auto s = ct_eq<999>{};
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(), s, undefined{}),
+ MAKE_TUPLE(s)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}), s, f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, s),
+ s
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), s, f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, s)),
+ f(ct_eq<1>{}, s),
+ s
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), s, f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, f(ct_eq<2>{}, s))),
+ f(ct_eq<1>{}, f(ct_eq<2>{}, s)),
+ f(ct_eq<2>{}, s),
+ s
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), s, f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, s)))),
+ f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, s))),
+ f(ct_eq<2>{}, f(ct_eq<3>{}, s)),
+ f(ct_eq<3>{}, s),
+ s
+ )
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::scan_right(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), s, f),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, f(ct_eq<4>{}, s))))),
+ f(ct_eq<1>{}, f(ct_eq<2>{}, f(ct_eq<3>{}, f(ct_eq<4>{}, s)))),
+ f(ct_eq<2>{}, f(ct_eq<3>{}, f(ct_eq<4>{}, s))),
+ f(ct_eq<3>{}, f(ct_eq<4>{}, s)),
+ f(ct_eq<4>{}, s),
+ s
+ )
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_SCANS_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/sequence.hpp b/src/boost/libs/hana/test/_include/auto/sequence.hpp
new file mode 100644
index 000000000..280b7355b
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/sequence.hpp
@@ -0,0 +1,13 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_SEQUENCE_HPP
+#define BOOST_HANA_TEST_AUTO_SEQUENCE_HPP
+
+#include <boost/hana/concept/sequence.hpp>
+
+
+static_assert(boost::hana::Sequence<TUPLE_TAG>::value, "");
+
+#endif // !BOOST_HANA_TEST_AUTO_SEQUENCE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/slice.hpp b/src/boost/libs/hana/test/_include/auto/slice.hpp
new file mode 100644
index 000000000..3beb2ef0a
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/slice.hpp
@@ -0,0 +1,182 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_SLICE_HPP
+#define BOOST_HANA_TEST_AUTO_SLICE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/slice.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/seq.hpp>
+
+#include <cstddef>
+
+
+TestCase test_slice{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ constexpr auto foldable = ::seq;
+
+ struct undefined { };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Test with arbitrary indices
+ //////////////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(),
+ foldable()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}),
+ foldable()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, undefined{}),
+ foldable()),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}),
+ foldable(hana::size_c<0>)),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, undefined{}),
+ foldable(hana::size_c<0>)),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, ct_eq<1>{}),
+ foldable(hana::size_c<1>)),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ foldable(hana::size_c<0>, hana::size_c<1>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ foldable(hana::size_c<1>, hana::size_c<0>)),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ foldable(hana::size_c<0>, hana::size_c<0>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ foldable(hana::size_c<1>, hana::size_c<1>)),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ foldable(hana::size_c<0>, hana::size_c<1>, hana::size_c<2>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ foldable(hana::size_c<0>, hana::size_c<2>, hana::size_c<1>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ foldable(hana::size_c<0>, hana::size_c<2>, hana::size_c<1>, hana::size_c<0>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ foldable(hana::size_c<0>, hana::size_c<2>, hana::size_c<1>, hana::size_c<0>, hana::size_c<1>)),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<2>{}, ct_eq<1>{}, ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ // Try with a tuple_c
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ hana::tuple_c<unsigned, 1, 3, 2>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<3>{}, ct_eq<2>{})
+ ));
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Test with a `range` (check the optimization for contiguous indices)
+ //////////////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(),
+ hana::range_c<std::size_t, 0, 0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}),
+ hana::range_c<std::size_t, 0, 0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, undefined{}),
+ hana::range_c<std::size_t, 0, 0>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}),
+ hana::range_c<std::size_t, 0, 1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, undefined{}),
+ hana::range_c<std::size_t, 0, 1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, ct_eq<1>{}),
+ hana::range_c<std::size_t, 1, 2>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, ct_eq<1>{}, undefined{}),
+ hana::range_c<std::size_t, 1, 2>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ hana::range_c<std::size_t, 0, 2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, undefined{}),
+ hana::range_c<std::size_t, 0, 2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, ct_eq<1>{}, ct_eq<2>{}),
+ hana::range_c<std::size_t, 1, 3>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::slice(MAKE_TUPLE(undefined{}, ct_eq<1>{}, ct_eq<2>{}, undefined{}),
+ hana::range_c<std::size_t, 1, 3>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_SLICE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/sort.hpp b/src/boost/libs/hana/test/_include/auto/sort.hpp
new file mode 100644
index 000000000..398584fef
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/sort.hpp
@@ -0,0 +1,111 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_SORT_HPP
+#define BOOST_HANA_TEST_AUTO_SORT_HPP
+
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/less.hpp>
+#include <boost/hana/permutations.hpp>
+#include <boost/hana/sort.hpp>
+#include <boost/hana/transform.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/equivalence_class.hpp>
+
+
+TestCase test_sort{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ using hana::test::ct_ord;
+
+ // Test without a custom predicate
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(ct_ord<0>{})),
+ MAKE_TUPLE(ct_ord<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{})),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(ct_ord<1>{}, ct_ord<0>{})),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(ct_ord<1>{}, ct_ord<0>{}, ct_ord<4>{}, ct_ord<2>{})),
+ MAKE_TUPLE(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, ct_ord<4>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(ct_ord<1>{}, ct_ord<0>{}, ct_ord<-4>{}, ct_ord<2>{})),
+ MAKE_TUPLE(ct_ord<-4>{}, ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{})
+ ));
+ }
+
+ // Test with a custom predicate
+ {
+ auto pred = [](auto x, auto y) {
+ return hana::less(x.unwrap, y.unwrap);
+ };
+ auto a = [](auto z) { return ::equivalence_class(ct_eq<999>{}, z); };
+ auto b = [](auto z) { return ::equivalence_class(ct_eq<888>{}, z); };
+
+ auto check = [=](auto ...sorted) {
+ auto perms = hana::transform(
+ hana::permutations(MAKE_TUPLE(a(sorted)...)),
+ hana::sort.by(pred)
+ );
+ BOOST_HANA_CONSTANT_CHECK(hana::all_of(perms, [=](auto xs) {
+ return hana::equal(xs, MAKE_TUPLE(a(sorted)...));
+ }));
+ };
+
+ check();
+ check(ct_ord<1>{});
+ check(ct_ord<1>{}, ct_ord<2>{});
+ check(ct_ord<1>{}, ct_ord<2>{}, ct_ord<3>{});
+
+ // check stability
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{})), pred),
+ MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(b(ct_ord<1>{}), a(ct_ord<1>{})), pred),
+ MAKE_TUPLE(b(ct_ord<1>{}), a(ct_ord<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{})), pred),
+ MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(a(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<1>{}), b(ct_ord<2>{})), pred),
+ MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(b(ct_ord<1>{}), a(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{})), pred),
+ MAKE_TUPLE(b(ct_ord<1>{}), a(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(a(ct_ord<2>{}), b(ct_ord<1>{}), b(ct_ord<2>{}), a(ct_ord<1>{})), pred),
+ MAKE_TUPLE(b(ct_ord<1>{}), a(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::sort(MAKE_TUPLE(a(ct_ord<1>{}), a(ct_ord<3>{}), b(ct_ord<1>{}), a(ct_ord<2>{}), b(ct_ord<3>{})), pred),
+ MAKE_TUPLE(a(ct_ord<1>{}), b(ct_ord<1>{}), a(ct_ord<2>{}), a(ct_ord<3>{}), b(ct_ord<3>{}))
+ ));
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_SORT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/span.hpp b/src/boost/libs/hana/test/_include/auto/span.hpp
new file mode 100644
index 000000000..1a15d408b
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/span.hpp
@@ -0,0 +1,84 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_SPAN_HPP
+#define BOOST_HANA_TEST_AUTO_SPAN_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/span.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/minimal_product.hpp>
+
+
+TestCase test_span{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto z = ct_eq<999>{};
+ auto pair = ::minimal_product;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE())
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(ct_eq<0>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(z), hana::equal.to(z)),
+ pair(MAKE_TUPLE(z), MAKE_TUPLE())
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, z), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(z, ct_eq<0>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(z), MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(z, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(z), MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<2>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(), MAKE_TUPLE(ct_eq<0>{}, z, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(z, z, ct_eq<2>{}), hana::equal.to(z)),
+ pair(MAKE_TUPLE(z, z), MAKE_TUPLE(ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span(MAKE_TUPLE(z, z, z), hana::equal.to(z)),
+ pair(MAKE_TUPLE(z, z, z), MAKE_TUPLE())
+ ));
+
+ // span.by
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span.by(hana::equal.to(z), MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(z))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::span.by(hana::equal.to(z))(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ hana::span(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), hana::equal.to(z))
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_SPAN_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/take_back.hpp b/src/boost/libs/hana/test/_include/auto/take_back.hpp
new file mode 100644
index 000000000..11a795e00
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/take_back.hpp
@@ -0,0 +1,82 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_TAKE_BACK_HPP
+#define BOOST_HANA_TEST_AUTO_TAKE_BACK_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/take_back.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_take_back{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_back(MAKE_TUPLE(
+ ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{},
+ ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{}),
+ hana::size_c<5>),
+ MAKE_TUPLE(ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_TAKE_BACK_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/take_front.hpp b/src/boost/libs/hana/test/_include/auto/take_front.hpp
new file mode 100644
index 000000000..5e9b67338
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/take_front.hpp
@@ -0,0 +1,77 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_TAKE_FRONT_HPP
+#define BOOST_HANA_TEST_AUTO_TAKE_FRONT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/take_front.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_take{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(), hana::size_c<1>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(), hana::size_c<2>),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}), hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<0>),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<1>),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<2>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}), hana::size_c<3>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_front(MAKE_TUPLE(
+ ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}, ct_eq<6>{},
+ ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{}, ct_eq<10>{}, ct_eq<11>{}, ct_eq<12>{}, ct_eq<13>{}),
+ hana::size_c<10>),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{},
+ ct_eq<5>{}, ct_eq<6>{}, ct_eq<7>{}, ct_eq<8>{}, ct_eq<9>{})
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_TAKE_FRONT_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/take_while.hpp b/src/boost/libs/hana/test/_include/auto/take_while.hpp
new file mode 100644
index 000000000..72d0b8b11
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/take_while.hpp
@@ -0,0 +1,68 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_TAKE_WHILE_HPP
+#define BOOST_HANA_TEST_AUTO_TAKE_WHILE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/take_while.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_take_while{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto z = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(), hana::not_equal.to(z)),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(z), hana::not_equal.to(z)),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}, z), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(z, ct_eq<2>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, z), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(ct_eq<1>{}, z, ct_eq<3>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE(ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::take_while(MAKE_TUPLE(z, ct_eq<2>{}, ct_eq<3>{}), hana::not_equal.to(z)),
+ MAKE_TUPLE()
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_TAKE_WHILE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/test_case.hpp b/src/boost/libs/hana/test/_include/auto/test_case.hpp
new file mode 100644
index 000000000..03de19ac0
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/test_case.hpp
@@ -0,0 +1,13 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_TEST_CASE_HPP
+#define BOOST_HANA_TEST_AUTO_TEST_CASE_HPP
+
+struct TestCase {
+ template <typename F>
+ explicit TestCase(F const& f) { f(); }
+};
+
+#endif // !BOOST_HANA_TEST_AUTO_TEST_CASE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/transform.hpp b/src/boost/libs/hana/test/_include/auto/transform.hpp
new file mode 100644
index 000000000..478d725ac
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/transform.hpp
@@ -0,0 +1,74 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_TRANSFORM_HPP
+#define BOOST_HANA_TEST_AUTO_TRANSFORM_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/transform.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+
+
+TestCase test_transform{[] {
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+ struct undefined { };
+ constexpr hana::test::_injection<0> f{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::transform(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::transform(MAKE_TUPLE(ct_eq<1>{}), f),
+ MAKE_TUPLE(f(ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::transform(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}), f),
+ MAKE_TUPLE(f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::transform(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), f),
+ MAKE_TUPLE(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::transform(MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), f),
+ MAKE_TUPLE(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}), f(ct_eq<4>{}))
+ ));
+
+#ifndef MAKE_TUPLE_NO_CONSTEXPR
+ struct incr {
+ constexpr int operator()(int i) const { return i + 1; }
+ };
+
+ static_assert(hana::equal(
+ hana::transform(MAKE_TUPLE(1), incr{}),
+ MAKE_TUPLE(2)
+ ), "");
+
+ static_assert(hana::equal(
+ hana::transform(MAKE_TUPLE(1, 2), incr{}),
+ MAKE_TUPLE(2, 3)
+ ), "");
+
+ static_assert(hana::equal(
+ hana::transform(MAKE_TUPLE(1, 2, 3), incr{}),
+ MAKE_TUPLE(2, 3, 4)
+ ), "");
+
+ static_assert(hana::equal(
+ hana::transform(MAKE_TUPLE(1, 2, 3, 4), incr{}),
+ MAKE_TUPLE(2, 3, 4, 5)
+ ), "");
+#endif
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_TRANSFORM_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/unfolds.hpp b/src/boost/libs/hana/test/_include/auto/unfolds.hpp
new file mode 100644
index 000000000..afa01d3fc
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/unfolds.hpp
@@ -0,0 +1,170 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_UNFOLDS_HPP
+#define BOOST_HANA_TEST_AUTO_UNFOLDS_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/unfold_left.hpp>
+#include <boost/hana/unfold_right.hpp>
+
+#include <laws/base.hpp>
+#include <support/minimal_product.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_unfold_left{[]{
+ namespace hana = boost::hana;
+
+ hana::test::_injection<0> f{};
+ auto stop_at = [=](auto stop) {
+ return [=](auto x) {
+ return hana::if_(hana::equal(stop, x),
+ hana::nothing,
+ hana::just(::minimal_product(x + hana::int_c<1>, f(x)))
+ );
+ };
+ };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<0>)),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<1>)),
+ MAKE_TUPLE(f(hana::int_c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<2>)),
+ MAKE_TUPLE(f(hana::int_c<1>), f(hana::int_c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<3>)),
+ MAKE_TUPLE(f(hana::int_c<2>), f(hana::int_c<1>), f(hana::int_c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<4>)),
+ MAKE_TUPLE(f(hana::int_c<3>), f(hana::int_c<2>), f(hana::int_c<1>), f(hana::int_c<0>))
+ ));
+}};
+
+
+TestCase test_unfold_right{[]{
+ namespace hana = boost::hana;
+
+ hana::test::_injection<0> f{};
+ auto stop_at = [=](auto stop) {
+ return [=](auto x) {
+ return hana::if_(hana::equal(stop, x),
+ hana::nothing,
+ hana::just(::minimal_product(f(x), x + hana::int_c<1>))
+ );
+ };
+ };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<0>)),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<1>)),
+ MAKE_TUPLE(f(hana::int_c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<2>)),
+ MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<3>)),
+ MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>), f(hana::int_c<2>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::int_c<0>, stop_at(hana::int_c<4>)),
+ MAKE_TUPLE(f(hana::int_c<0>), f(hana::int_c<1>), f(hana::int_c<2>), f(hana::int_c<3>))
+ ));
+}};
+
+// Make sure unfolds can be reversed under certain conditions.
+TestCase test_unfold_undo{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ auto z = ct_eq<999>{};
+ auto f = ::minimal_product;
+ auto g = [=](auto k) {
+ return hana::if_(hana::equal(k, z),
+ hana::nothing,
+ hana::just(k)
+ );
+ };
+
+ // Make sure the special conditions are met
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ g(z),
+ hana::nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ g(f(ct_eq<0>{}, z)),
+ hana::just(::minimal_product(ct_eq<0>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ g(f(z, ct_eq<0>{})),
+ hana::just(::minimal_product(z, ct_eq<0>{}))
+ ));
+
+ // Make sure the reversing works
+ {
+ auto xs = MAKE_TUPLE();
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
+ xs
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
+ xs
+ ));
+ }
+ {
+ auto xs = MAKE_TUPLE(ct_eq<0>{});
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
+ xs
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
+ xs
+ ));
+ }
+ {
+ auto xs = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{});
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
+ xs
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
+ xs
+ ));
+ }
+ {
+ auto xs = MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{});
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_left<TUPLE_TAG>(hana::fold_left(xs, z, f), g),
+ xs
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unfold_right<TUPLE_TAG>(hana::fold_right(xs, z, f), g),
+ xs
+ ));
+ }
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_UNFOLDS_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/unique.hpp b/src/boost/libs/hana/test/_include/auto/unique.hpp
new file mode 100644
index 000000000..8ef7076fb
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/unique.hpp
@@ -0,0 +1,158 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_UNIQUE_HPP
+#define BOOST_HANA_TEST_AUTO_UNIQUE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/unique.hpp>
+
+#include "test_case.hpp"
+#include <laws/base.hpp>
+#include <support/equivalence_class.hpp>
+
+
+TestCase test_unique{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<1>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(
+ ct_eq<0>{}, ct_eq<0>{},
+ ct_eq<1>{},
+ ct_eq<2>{}, ct_eq<2>{}, ct_eq<2>{},
+ ct_eq<3>{}, ct_eq<3>{}, ct_eq<3>{},
+ ct_eq<0>{})),
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<0>{})
+ ));
+}};
+
+TestCase test_unique_by{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ struct undefined { };
+
+ auto a = [](auto z) { return ::equivalence_class(ct_eq<999>{}, z); };
+ auto b = [](auto z) { return ::equivalence_class(ct_eq<888>{}, z); };
+ auto c = [](auto z) { return ::equivalence_class(ct_eq<777>{}, z); };
+
+ auto pred = [](auto x, auto y) {
+ return hana::equal(x.unwrap, y.unwrap);
+ };
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(), undefined{}),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), c(ct_eq<0>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<0>{}), c(ct_eq<1>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), c(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<0>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<1>{}), b(ct_eq<1>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), b(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<2>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique(MAKE_TUPLE(
+ a(ct_eq<0>{}), b(ct_eq<0>{}),
+ a(ct_eq<1>{}),
+ a(ct_eq<2>{}), b(ct_eq<2>{}), c(ct_eq<2>{}),
+ a(ct_eq<3>{}), b(ct_eq<3>{}), c(ct_eq<3>{}),
+ a(ct_eq<0>{})), pred),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<2>{}), a(ct_eq<3>{}), a(ct_eq<0>{}))
+ ));
+
+ // unique.by
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique.by(pred, MAKE_TUPLE(
+ a(ct_eq<0>{}), b(ct_eq<0>{}),
+ a(ct_eq<1>{}),
+ a(ct_eq<2>{}), b(ct_eq<2>{}), c(ct_eq<2>{}),
+ a(ct_eq<3>{}), b(ct_eq<3>{}), c(ct_eq<3>{}),
+ a(ct_eq<0>{}))),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<2>{}), a(ct_eq<3>{}), a(ct_eq<0>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::unique.by(pred)(MAKE_TUPLE(
+ a(ct_eq<0>{}), b(ct_eq<0>{}),
+ a(ct_eq<1>{}),
+ a(ct_eq<2>{}), b(ct_eq<2>{}), c(ct_eq<2>{}),
+ a(ct_eq<3>{}), b(ct_eq<3>{}), c(ct_eq<3>{}),
+ a(ct_eq<0>{}))),
+ MAKE_TUPLE(a(ct_eq<0>{}), a(ct_eq<1>{}), a(ct_eq<2>{}), a(ct_eq<3>{}), a(ct_eq<0>{}))
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_UNIQUE_HPP
diff --git a/src/boost/libs/hana/test/_include/auto/zips.hpp b/src/boost/libs/hana/test/_include/auto/zips.hpp
new file mode 100644
index 000000000..3d129c90d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/auto/zips.hpp
@@ -0,0 +1,342 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_AUTO_ZIPS_HPP
+#define BOOST_HANA_TEST_AUTO_ZIPS_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/zip.hpp>
+#include <boost/hana/zip_shortest.hpp>
+#include <boost/hana/zip_shortest_with.hpp>
+#include <boost/hana/zip_with.hpp>
+
+#include <laws/base.hpp>
+#include "test_case.hpp"
+
+
+TestCase test_zip_shortest_with{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ hana::test::_injection<0> f{};
+ auto zip = hana::zip_shortest_with;
+ struct undefined { };
+
+ // zip 1
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ // zip 2
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(undefined{}), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(undefined{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<-1>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}), MAKE_TUPLE(ct_eq<-1>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}), MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}), f(ct_eq<2>{}, ct_eq<-2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<-3>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}),
+ f(ct_eq<2>{}, ct_eq<-2>{}),
+ f(ct_eq<3>{}, ct_eq<-3>{}))
+ ));
+
+ // zip 3
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(undefined{}), MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(undefined{}), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(), MAKE_TUPLE(undefined{})),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(undefined{}), MAKE_TUPLE(undefined{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(undefined{}), MAKE_TUPLE(), MAKE_TUPLE(undefined{})),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(undefined{}, MAKE_TUPLE(undefined{}), MAKE_TUPLE(undefined{}), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f, MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
+ ));
+
+ // zip 4
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f,
+ MAKE_TUPLE(ct_eq<11>{}, ct_eq<12>{}, ct_eq<13>{}, ct_eq<14>{}),
+ MAKE_TUPLE(ct_eq<21>{}, ct_eq<22>{}, ct_eq<23>{}),
+ MAKE_TUPLE(ct_eq<31>{}, ct_eq<32>{}, ct_eq<33>{}, ct_eq<34>{}),
+ MAKE_TUPLE(ct_eq<41>{}, ct_eq<42>{}, ct_eq<43>{}, ct_eq<44>{}, ct_eq<45>{})
+ ),
+ MAKE_TUPLE(
+ f(ct_eq<11>{}, ct_eq<21>{}, ct_eq<31>{}, ct_eq<41>{}),
+ f(ct_eq<12>{}, ct_eq<22>{}, ct_eq<32>{}, ct_eq<42>{}),
+ f(ct_eq<13>{}, ct_eq<23>{}, ct_eq<33>{}, ct_eq<43>{})
+ )
+ ));
+
+ // zip 5
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ zip(f,
+ MAKE_TUPLE(ct_eq<11>{}, ct_eq<12>{}, ct_eq<13>{}, ct_eq<14>{}),
+ MAKE_TUPLE(ct_eq<21>{}, ct_eq<22>{}, ct_eq<23>{}, ct_eq<24>{}, ct_eq<25>{}),
+ MAKE_TUPLE(ct_eq<31>{}, ct_eq<32>{}, ct_eq<33>{}, ct_eq<34>{}),
+ MAKE_TUPLE(ct_eq<41>{}, ct_eq<42>{}, ct_eq<43>{}, ct_eq<44>{}, ct_eq<45>{}, ct_eq<46>{}),
+ MAKE_TUPLE(ct_eq<51>{}, ct_eq<52>{}, ct_eq<53>{}, ct_eq<54>{}, ct_eq<55>{})
+ ),
+ MAKE_TUPLE(
+ f(ct_eq<11>{}, ct_eq<21>{}, ct_eq<31>{}, ct_eq<41>{}, ct_eq<51>{}),
+ f(ct_eq<12>{}, ct_eq<22>{}, ct_eq<32>{}, ct_eq<42>{}, ct_eq<52>{}),
+ f(ct_eq<13>{}, ct_eq<23>{}, ct_eq<33>{}, ct_eq<43>{}, ct_eq<53>{}),
+ f(ct_eq<14>{}, ct_eq<24>{}, ct_eq<34>{}, ct_eq<44>{}, ct_eq<54>{})
+ )
+ ));
+}};
+
+TestCase test_zip_with{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ hana::test::_injection<0> f{};
+ struct undefined { };
+
+ // zip 1
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(undefined{}, MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ // zip 2
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(undefined{}, MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<-1>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}), MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{})),
+ MAKE_TUPLE(f(ct_eq<1>{}, ct_eq<-1>{}), f(ct_eq<2>{}, ct_eq<-2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f,
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<-1>{}, ct_eq<-2>{}, ct_eq<-3>{})),
+ MAKE_TUPLE(
+ f(ct_eq<1>{}, ct_eq<-1>{}),
+ f(ct_eq<2>{}, ct_eq<-2>{}),
+ f(ct_eq<3>{}, ct_eq<-3>{}))
+ ));
+
+ // zip 3
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(undefined{}, MAKE_TUPLE(), MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f, MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<2>{})),
+ MAKE_TUPLE(f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f,
+ MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<4>{}, ct_eq<5>{})
+ ),
+ MAKE_TUPLE(
+ f(ct_eq<0>{}, ct_eq<2>{}, ct_eq<4>{}),
+ f(ct_eq<1>{}, ct_eq<3>{}, ct_eq<5>{})
+ )
+ ));
+
+ // zip 4
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f,
+ MAKE_TUPLE(ct_eq<11>{}, ct_eq<12>{}, ct_eq<13>{}),
+ MAKE_TUPLE(ct_eq<21>{}, ct_eq<22>{}, ct_eq<23>{}),
+ MAKE_TUPLE(ct_eq<31>{}, ct_eq<32>{}, ct_eq<33>{}),
+ MAKE_TUPLE(ct_eq<41>{}, ct_eq<42>{}, ct_eq<43>{})
+ ),
+ MAKE_TUPLE(
+ f(ct_eq<11>{}, ct_eq<21>{}, ct_eq<31>{}, ct_eq<41>{}),
+ f(ct_eq<12>{}, ct_eq<22>{}, ct_eq<32>{}, ct_eq<42>{}),
+ f(ct_eq<13>{}, ct_eq<23>{}, ct_eq<33>{}, ct_eq<43>{})
+ )
+ ));
+
+ // zip 5
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_with(f,
+ MAKE_TUPLE(ct_eq<11>{}, ct_eq<12>{}, ct_eq<13>{}, ct_eq<14>{}),
+ MAKE_TUPLE(ct_eq<21>{}, ct_eq<22>{}, ct_eq<23>{}, ct_eq<24>{}),
+ MAKE_TUPLE(ct_eq<31>{}, ct_eq<32>{}, ct_eq<33>{}, ct_eq<34>{}),
+ MAKE_TUPLE(ct_eq<41>{}, ct_eq<42>{}, ct_eq<43>{}, ct_eq<44>{}),
+ MAKE_TUPLE(ct_eq<51>{}, ct_eq<52>{}, ct_eq<53>{}, ct_eq<54>{})
+ ),
+ MAKE_TUPLE(
+ f(ct_eq<11>{}, ct_eq<21>{}, ct_eq<31>{}, ct_eq<41>{}, ct_eq<51>{}),
+ f(ct_eq<12>{}, ct_eq<22>{}, ct_eq<32>{}, ct_eq<42>{}, ct_eq<52>{}),
+ f(ct_eq<13>{}, ct_eq<23>{}, ct_eq<33>{}, ct_eq<43>{}, ct_eq<53>{}),
+ f(ct_eq<14>{}, ct_eq<24>{}, ct_eq<34>{}, ct_eq<44>{}, ct_eq<54>{})
+ )
+ ));
+}};
+
+TestCase test_zip{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<2>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip(MAKE_TUPLE(ct_eq<0>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<4>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<5>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}))
+ ));
+}};
+
+TestCase test_zip_shortest{[]{
+ namespace hana = boost::hana;
+ using hana::test::ct_eq;
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{}), MAKE_TUPLE(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(), MAKE_TUPLE()),
+ MAKE_TUPLE()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{}), MAKE_TUPLE(ct_eq<1>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{}),
+ MAKE_TUPLE(ct_eq<1>{}),
+ MAKE_TUPLE(ct_eq<2>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::zip_shortest(MAKE_TUPLE(ct_eq<0>{}, ct_eq<3>{}),
+ MAKE_TUPLE(ct_eq<1>{}, ct_eq<4>{}),
+ MAKE_TUPLE(ct_eq<2>{}, ct_eq<5>{}, ct_eq<8>{})),
+ MAKE_TUPLE(MAKE_TUPLE(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
+ MAKE_TUPLE(ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}))
+ ));
+}};
+
+#endif // !BOOST_HANA_TEST_AUTO_ZIPS_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/applicative.hpp b/src/boost/libs/hana/test/_include/laws/applicative.hpp
new file mode 100644
index 000000000..a7de47b9d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/applicative.hpp
@@ -0,0 +1,196 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP
+#define BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP
+
+#include <boost/hana/ap.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/applicative.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/placeholder.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/take_front.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestApplicative : TestApplicative<F, laws> {
+ using TestApplicative<F, laws>::TestApplicative;
+ };
+
+ template <typename F>
+ struct TestApplicative<F, laws> {
+ template <typename Applicatives>
+ TestApplicative(Applicatives applicatives) {
+ hana::for_each(applicatives, [](auto a) {
+ static_assert(Applicative<decltype(a)>{}, "");
+ });
+
+ auto functions1 = hana::take_front(
+ hana::transform(applicatives, [](auto xs) {
+ return hana::transform(xs, hana::curry<2>(test::_injection<0>{}));
+ }), hana::int_c<3>);
+
+ auto functions2 = hana::take_front(
+ hana::transform(applicatives, [](auto xs) {
+ return hana::transform(xs, hana::curry<2>(test::_injection<1>{}));
+ }), hana::int_c<3>);
+
+ // identity
+ {
+ hana::for_each(applicatives, [](auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(hana::lift<F>(hana::id), xs),
+ xs
+ ));
+ });
+ }
+
+ // composition
+ {
+ hana::for_each(applicatives, hana::capture(functions1, functions2)(
+ [](auto functions1, auto functions2, auto xs) {
+ hana::for_each(functions1, hana::capture(functions2, xs)(
+ [](auto functions2, auto xs, auto fs) {
+ hana::for_each(functions2, hana::capture(xs, fs)(
+ [](auto xs, auto fs, auto gs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(hana::ap(hana::lift<F>(compose), fs, gs), xs),
+ hana::ap(fs, hana::ap(gs, xs))
+ ));
+ }));}));}));
+ }
+
+ // homomorphism
+ {
+ test::_injection<0> f{};
+ test::ct_eq<3> x{};
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(hana::lift<F>(f), hana::lift<F>(x)),
+ hana::lift<F>(f(x))
+ ));
+ }
+
+ // interchange
+ {
+ hana::for_each(functions1, [](auto fs) {
+ test::ct_eq<4> x{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(fs, hana::lift<F>(x)),
+ hana::ap(hana::lift<F>(hana::_(x)), fs)
+ ));
+ });
+ }
+
+ // definition of transform
+ {
+ hana::for_each(applicatives, [](auto xs) {
+ test::_injection<0> f{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(xs, f),
+ hana::ap(hana::lift<F>(f), xs)
+ ));
+ });
+ }
+ }
+ };
+
+ template <typename S>
+ struct TestApplicative<S, when<Sequence<S>::value>>
+ : TestApplicative<S, laws>
+ {
+ template <typename Applicatives>
+ TestApplicative(Applicatives applicatives)
+ : TestApplicative<S, laws>{applicatives}
+ {
+ _injection<0> f{};
+ _injection<1> g{};
+ using test::ct_eq;
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // ap
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{})),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{})),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{})),
+ list(f(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{})),
+ list(f(ct_eq<0>{}), g(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), g(ct_eq<0>{}), g(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}),
+ g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // lift
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ lift<S>(ct_eq<0>{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ lift<S>(ct_eq<1>{}),
+ list(ct_eq<1>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/base.hpp b/src/boost/libs/hana/test/_include/laws/base.hpp
new file mode 100644
index 000000000..0f421b8ae
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/base.hpp
@@ -0,0 +1,369 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_BASE_HPP
+#define BOOST_HANA_TEST_LAWS_BASE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/wrong.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/infix.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/concept/integral_constant.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <support/tracked.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Misc
+ //////////////////////////////////////////////////////////////////////////
+ namespace test {
+ struct laws;
+
+ template <int i>
+ struct for_each_n_t {
+ static_assert(i > 0, "can't use for_each_n with i < 0");
+
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs const& xs, F const& f) const {
+ hana::for_each(xs,
+ hana::compose(
+ hana::partial(for_each_n_t<i - 1>{}, xs),
+ hana::partial(hana::partial, f)
+ )
+ );
+ }
+ };
+
+ template <>
+ struct for_each_n_t<1> {
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs const& xs, F const& f) const {
+ hana::for_each(xs, f);
+ }
+ };
+
+ template <int i>
+ constexpr for_each_n_t<i> for_each_n{};
+
+ auto foreach = hana::for_each;
+ constexpr auto foreach3 = for_each_n<3>;
+ constexpr auto foreach2 = for_each_n<2>;
+
+ struct implies_t {
+ template <typename P, typename Q>
+ constexpr decltype(auto) operator()(P&& p, Q&& q) const {
+ return hana::or_(hana::not_(static_cast<P&&>(p)),
+ static_cast<Q&&>(q));
+ }
+ };
+ constexpr auto implies = hana::infix(implies_t{});
+
+ struct iff_t {
+ template <typename P, typename Q>
+ constexpr decltype(auto) operator()(P&& p, Q&& q) const {
+ return hana::and_(implies(p, q), implies(q, p));
+ }
+ };
+ constexpr auto iff = hana::infix(iff_t{});
+
+ template <typename Cond, typename F>
+ constexpr decltype(auto) only_when_(Cond cond, F f) {
+ return hana::eval_if(cond, f, [](auto){ });
+ }
+
+ // A type with a constructor that must not be instantiated.
+ // This is to make sure we don't instantiate something else than
+ // the copy-constructor of the elements inside a container when we
+ // copy the container.
+ struct trap_construct {
+ trap_construct() = default;
+ trap_construct(trap_construct const&) = default;
+#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
+ trap_construct(trap_construct&) = default;
+#endif
+ trap_construct(trap_construct&&) = default;
+
+ template <typename X>
+ trap_construct(X&&) {
+ static_assert(detail::wrong<X>{},
+ "this constructor must not be instantiated");
+ }
+ };
+
+ // A move-only type. Useful for testing containers.
+ struct move_only {
+ move_only() = default;
+ move_only(move_only const&) = delete;
+ move_only(move_only&&) = default;
+ };
+
+ //////////////////////////////////////////////////////////////////////
+ // InjectionResult
+ //////////////////////////////////////////////////////////////////////
+ struct InjectionResult { };
+
+ template <int i, typename ...X>
+ struct injection_result {
+ using hana_tag = InjectionResult;
+ static constexpr int injection_id = i;
+ hana::tuple<X...> args;
+ Tracked tracker;
+
+ template <typename ...Y, typename = decltype(tuple<X...>{std::declval<Y>()...})>
+ constexpr explicit injection_result(Y&& ...y)
+ : args{static_cast<Y&&>(y)...}, tracker{i}
+ { }
+ };
+
+ //! A monotonic injective function.
+ //!
+ //! This is used in the unit tests, where we often just need a function
+ //! which preserves equality and order, but which also satisfies the
+ //! following law for all `Injection`s `f` and `g`:
+ //! @code
+ //! f(x) == g(x) if and only if f === g
+ //! @endcode
+ //! where `===` means _was created by the same call to `injection`_.
+ //! This allows creating several such functions in the unit tests while
+ //! conserving precious information such as the fact that
+ //! `f(g(x)) != g(f(x))`.
+ template <int i>
+ struct _injection {
+ template <typename ...X>
+ constexpr auto operator()(X&& ...x) const {
+ return injection_result<i,
+ typename std::decay<X>::type...
+ >{static_cast<X&&>(x)...};
+ }
+ };
+ } // end namespace test
+
+ template <>
+ struct equal_impl<test::InjectionResult, test::InjectionResult> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y) {
+ return hana::and_(
+ hana::bool_c<X::injection_id == Y::injection_id>,
+ hana::equal(x.args, y.args)
+ );
+ }
+ };
+
+ template <>
+ struct less_impl<test::InjectionResult, test::InjectionResult> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y) {
+ static_assert(X::injection_id == Y::injection_id,
+ "can't order the result of two different injections");
+ return hana::less(x.args, y.args);
+ }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Integer
+ //////////////////////////////////////////////////////////////////////////
+ namespace test {
+ enum class Policy : int {
+ // One of those is mandatory
+ Constant = 1 << 0
+ , Constexpr = 1 << 1
+ , Runtime = 1 << 2
+
+ // Those are optional
+ , Tracked = 1 << 3
+ , Comparable = 1 << 4
+ , Orderable = 1 << 5
+ };
+
+ constexpr bool operator&&(Policy a, Policy b) {
+ return static_cast<int>(a) && static_cast<int>(b);
+ }
+
+ constexpr bool operator&&(Policy a, bool b) {
+ return static_cast<int>(a) && b;
+ }
+
+ constexpr bool operator&&(bool a, Policy b) {
+ return a && static_cast<int>(b);
+ }
+
+ constexpr bool operator||(Policy a, Policy b) {
+ return static_cast<int>(a) || static_cast<int>(b);
+ }
+
+ constexpr bool operator||(Policy a, bool b) {
+ return static_cast<int>(a) || b;
+ }
+
+ constexpr bool operator||(bool a, Policy b) {
+ return a || static_cast<int>(b);
+ }
+
+ constexpr bool operator!(Policy a) {
+ return !static_cast<int>(a);
+ }
+
+ constexpr Policy operator|(Policy a, Policy b) {
+ return static_cast<Policy>(static_cast<int>(a) | static_cast<int>(b));
+ }
+
+ constexpr Policy operator&(Policy a, Policy b) {
+ return static_cast<Policy>(static_cast<int>(a) & static_cast<int>(b));
+ }
+
+ template <Policy policy, typename = void>
+ struct Integer { };
+
+ template <Policy policy>
+ struct Integer<policy, std::enable_if_t<!!(policy & Policy::Constant)>> {
+ using value_type = int;
+ };
+
+ template <int i, Policy policy, typename = void>
+ struct integer {
+ static_assert(
+ !!(policy & (Policy::Constant | Policy::Constexpr | Policy::Runtime))
+ , "You must choose at least one of Constant, Constexpr and Runtime.");
+
+ static constexpr int value = i;
+ constexpr operator int() const { return value; }
+ using hana_tag = Integer<policy>;
+ Tracked tracker{i};
+ };
+
+ template <int i, Policy policy>
+ struct integer <i, policy, std::enable_if_t<!!(policy & Policy::Constexpr)>> {
+ static constexpr int value = i;
+ constexpr operator int() const { return value; }
+ using hana_tag = Integer<policy>;
+ };
+
+ template <int i>
+ struct eq : integer<i, Policy::Comparable | Policy::Runtime> { };
+
+ template <int i>
+ struct ct_eq : integer<i, Policy::Comparable | Policy::Constant> { };
+
+ template <int i>
+ struct cx_eq : integer<i, Policy::Comparable | Policy::Constexpr> { };
+
+ template <int i>
+ struct ord : integer<i, Policy::Orderable | Policy::Runtime> { };
+
+ template <int i>
+ struct ct_ord : integer<i, Policy::Orderable | Policy::Constant> { };
+
+ template <int i>
+ struct cx_ord : integer<i, Policy::Orderable | Policy::Constexpr> { };
+
+ template <int i>
+ struct _constant
+ : integer<i, Policy::Constant | Policy::Comparable | Policy::Orderable>
+ { };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Constant/IntegralConstant
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy policy>
+ struct IntegralConstant<test::Integer<policy>> {
+ static constexpr bool value = static_cast<bool>(policy & test::Policy::Constant);
+ };
+
+ template <test::Policy policy, typename C>
+ struct to_impl<test::Integer<policy>, C, when<
+ (policy & test::Policy::Constant) &&
+ hana::IntegralConstant<C>::value
+ >>
+ : embedding<is_embedded<typename C::value_type, int>::value>
+ {
+ template <typename N>
+ static constexpr auto apply(N const&) {
+ return test::integer<N::value, policy>{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy p1, test::Policy p2>
+ struct equal_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Comparable or Orderable
+ (p1 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+ (p2 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+
+ // one Constexpr and the other Constant, or both Constexpr
+ (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr)))
+ >> {
+ template <typename X, typename Y>
+ static constexpr bool apply(X const&, Y const&)
+ { return X::value == Y::value; }
+ };
+
+ template <test::Policy p1, test::Policy p2>
+ struct equal_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Comparable or Orderable
+ (p1 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+ (p2 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+
+ // either one is Runtime
+ ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime))
+ >> {
+ template <typename X, typename Y>
+ static bool apply(X const&, Y const&)
+ { return X::value == Y::value; }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy p1, test::Policy p2>
+ struct less_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Orderable
+ (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) &&
+
+ // one Constexpr and the other Constant, or both Constexpr
+ (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr)))
+ >> {
+ template <typename X, typename Y>
+ static constexpr bool apply(X const&, Y const&)
+ { return X::value < Y::value; }
+ };
+
+ template <test::Policy p1, test::Policy p2>
+ struct less_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Orderable
+ (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) &&
+
+ // either one is Runtime
+ ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime))
+ >> {
+ template <typename X, typename Y>
+ static bool apply(X const&, Y const&)
+ { return X::value < Y::value; }
+ };
+}} // end namespace boost::hana
+
+#endif // !BOOST_HANA_TEST_LAWS_BASE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/comonad.hpp b/src/boost/libs/hana/test/_include/laws/comonad.hpp
new file mode 100644
index 000000000..82ef7b32d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/comonad.hpp
@@ -0,0 +1,53 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_COMONAD_HPP
+#define BOOST_HANA_TEST_LAWS_COMONAD_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/functor.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename W, typename = when<true>>
+ struct TestComonad : TestComonad<W, laws> {
+ using TestComonad<W, laws>::TestComonad;
+ };
+
+ template <typename W>
+ struct TestComonad<W, laws> {
+ template <typename Ws>
+ TestComonad(Ws ws) {
+ hana::for_each(ws, [](auto w) {
+ static_assert(Comonad<decltype(w)>{}, "");
+
+ // extract(duplicate(w)) == w
+ BOOST_HANA_CHECK(hana::equal(
+ hana::extract(hana::duplicate(w)),
+ w
+ ));
+
+ // transform(duplicate(w), extract) == w
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(hana::duplicate(w), extract),
+ w
+ ));
+
+ // duplicate(duplicate(w)) == transform(duplicate(w), duplicate)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::duplicate(hana::duplicate(w)),
+ hana::transform(hana::duplicate(w), duplicate)
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_COMONAD_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/comparable.hpp b/src/boost/libs/hana/test/_include/laws/comparable.hpp
new file mode 100644
index 000000000..24ce317b8
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/comparable.hpp
@@ -0,0 +1,167 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_COMPARABLE_HPP
+#define BOOST_HANA_TEST_LAWS_COMPARABLE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/comparing.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename T, typename = hana::when<true>>
+ struct TestComparable : TestComparable<T, laws> {
+ using TestComparable<T, laws>::TestComparable;
+ };
+
+ template <typename T>
+ struct TestComparable<T, laws> {
+ template <typename Xs>
+ TestComparable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(hana::Comparable<decltype(x)>{}, "");
+ });
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // reflexivity
+ BOOST_HANA_CHECK(
+ hana::equal(a, a)
+ );
+
+ // symmetry
+ BOOST_HANA_CHECK(
+ hana::equal(a, b) ^implies^ hana::equal(b, a)
+ );
+
+ // `not_equal` is the negation of `equal`
+ BOOST_HANA_CHECK(
+ hana::not_equal(a, b) ^iff^ hana::not_(hana::equal(a, b))
+ );
+
+ // equal.to and not_equal.to
+ BOOST_HANA_CHECK(
+ hana::equal.to(a)(b) ^iff^ hana::equal(a, b)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::not_equal.to(a)(b) ^iff^ hana::not_equal(a, b)
+ );
+
+ // comparing
+ _injection<0> f{};
+ BOOST_HANA_CHECK(
+ hana::comparing(f)(a, b) ^iff^ hana::equal(f(a), f(b))
+ );
+ });
+
+ // transitivity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(
+ hana::and_(hana::equal(a, b), hana::equal(b, c))
+ ^implies^ hana::equal(a, c)
+ );
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestComparable<C, when<Constant<C>::value>>
+ : TestComparable<C, laws>
+ {
+ template <typename Xs>
+ TestComparable(Xs xs) : TestComparable<C, laws>{xs} {
+ foreach2(xs, [](auto a, auto b) {
+ BOOST_HANA_CHECK(
+ hana::value(hana::equal(a, b)) ^iff^
+ hana::equal(hana::value(a), hana::value(b))
+ );
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestComparable<P, when<Product<P>::value>>
+ : TestComparable<P, laws>
+ {
+ template <typename Products>
+ TestComparable(Products products) : TestComparable<P, laws>{products} {
+ foreach2(products, [](auto x, auto y) {
+ BOOST_HANA_CHECK(
+ hana::equal(x, y) ^iff^
+ hana::and_(
+ hana::equal(hana::first(x), hana::first(y)),
+ hana::equal(hana::second(x), hana::second(y))
+ )
+ );
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestComparable<S, when<Sequence<S>::value>>
+ : TestComparable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <typename Xs>
+ TestComparable(Xs xs) : TestComparable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // equal
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}),
+ list()
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(x<0>{}),
+ list(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{}, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}, x<1>{}, x<2>{}, x<3>{}),
+ list(x<0>{}, x<1>{}, x<2>{}, x<4>{})
+ )));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_COMPARABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/constant.hpp b/src/boost/libs/hana/test/_include/laws/constant.hpp
new file mode 100644
index 000000000..1acd335e4
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/constant.hpp
@@ -0,0 +1,106 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_CONSTANT_HPP
+#define BOOST_HANA_TEST_LAWS_CONSTANT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/concept/logical.hpp>
+
+#include <laws/base.hpp>
+#include <laws/comparable.hpp>
+#include <laws/euclidean_ring.hpp>
+#include <laws/group.hpp>
+#include <laws/logical.hpp>
+#include <laws/monoid.hpp>
+#include <laws/orderable.hpp>
+#include <laws/ring.hpp>
+
+#include <type_traits>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename C, typename = when<true>>
+ struct TestConstant {
+ using T = typename C::value_type;
+
+ template <typename X>
+ struct wrap_arbitrary_constant {
+ static constexpr bool value = boost::hana::value<X>();
+ using hana_tag = detail::CanonicalConstant<T>;
+ };
+
+ template <typename Xs, typename Convertibles>
+ TestConstant(Xs xs, Convertibles types) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Constant<decltype(x)>{}, "");
+ });
+
+ hana::for_each(xs, hana::capture(types)([](auto types, auto c) {
+
+ // constexpr-ness of hana::value(c)
+ constexpr auto must_be_constexpr1 = hana::value(c);
+ constexpr auto must_be_constexpr2 = hana::value<decltype(c)>();
+ (void)must_be_constexpr1;
+ (void)must_be_constexpr2;
+
+ // consistency of C::value_type
+ static_assert(std::is_same<
+ T,
+ tag_of_t<decltype(hana::value(c))>
+ >{}, "");
+
+ // equivalence of value_of(c) and value<decltype(c)>
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value_of(c),
+ hana::value<decltype(c)>()
+ ));
+
+ // equivalence of value<decltype(c)>() and value(c)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value<decltype(c)>(),
+ hana::value(c)
+ ));
+
+ // conversion from an arbitrary Constant
+ (void)to<C>(wrap_arbitrary_constant<decltype(c)>{});
+ static_assert(is_embedded<detail::CanonicalConstant<T>, C>{}, "");
+
+ hana::for_each(types, hana::capture(c)([](auto c, auto u) {
+ using U = typename decltype(u)::type;
+
+ // conversion to something to which the underlying data
+ // type can be converted.
+ BOOST_HANA_CHECK(equal(
+ to<U>(c),
+ make<U>(hana::value(c))
+ ));
+ static_assert(is_embedded<C, U>::value ^iff^ is_embedded<T, U>::value, "");
+
+ // common data type
+ static_assert(std::is_same<
+ common_t<C, detail::CanonicalConstant<U>>,
+ detail::CanonicalConstant<common_t<T, U>>
+ >{}, "");
+
+ static_assert(std::is_same<
+ common_t<detail::CanonicalConstant<U>, C>,
+ detail::CanonicalConstant<common_t<T, U>>
+ >{}, "");
+
+ static_assert(std::is_same<
+ common_t<C, U>,
+ common_t<typename C::value_type, U>
+ >{}, "");
+ }));
+ }));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_CONSTANT_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp
new file mode 100644
index 000000000..96d1fce58
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp
@@ -0,0 +1,99 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
+#define BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/euclidean_ring.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/div.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/mod.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/value.hpp>
+#include <boost/hana/zero.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename D, typename = when<true>>
+ struct TestEuclideanRing : TestEuclideanRing<D, laws> {
+ using TestEuclideanRing<D, laws>::TestEuclideanRing;
+ };
+
+ template <typename D>
+ struct TestEuclideanRing<D, laws> {
+ template <typename Xs>
+ TestEuclideanRing(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(EuclideanRing<decltype(x)>{}, "");
+ });
+
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<D>(); // force adding zero<D>'s member function to pending temploid list
+#endif
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // commutativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(a, b),
+ hana::mult(b, a)
+ ));
+
+ only_when_(hana::not_equal(b, zero<D>()),
+ hana::make_lazy([](auto a, auto b) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(
+ hana::mult(hana::div(a, b), b),
+ hana::mod(a, b)
+ ),
+ a
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mod(zero<D>(), b),
+ zero<D>()
+ ));
+ })(a, b));
+
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestEuclideanRing<C, when<Constant<C>::value>>
+ : TestEuclideanRing<C, laws>
+ {
+ template <typename Xs>
+ TestEuclideanRing(Xs xs) : TestEuclideanRing<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+ only_when_(hana::not_equal(zero<C>(), y),
+ hana::make_lazy([](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::div(hana::value(x), hana::value(y)),
+ hana::value(hana::div(x, y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mod(hana::value(x), hana::value(y)),
+ hana::value(hana::mod(x, y))
+ ));
+
+ })(x, y));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/foldable.hpp b/src/boost/libs/hana/test/_include/laws/foldable.hpp
new file mode 100644
index 000000000..57411f416
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/foldable.hpp
@@ -0,0 +1,1104 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_FOLDABLE_HPP
+#define BOOST_HANA_TEST_LAWS_FOLDABLE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/count.hpp>
+#include <boost/hana/count_if.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/fold.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/demux.hpp>
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/maximum.hpp>
+#include <boost/hana/minimum.hpp>
+#include <boost/hana/monadic_fold_left.hpp>
+#include <boost/hana/monadic_fold_right.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/product.hpp>
+#include <boost/hana/reverse_fold.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/size.hpp>
+#include <boost/hana/sum.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+#include <support/identity.hpp>
+
+#include <vector>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestFoldable : TestFoldable<F, laws> {
+ using TestFoldable<F, laws>::TestFoldable;
+ };
+
+ template <typename F>
+ struct TestFoldable<F, laws> {
+ template <typename Foldables>
+ TestFoldable(Foldables foldables) {
+ hana::for_each(foldables, [](auto xs) {
+ static_assert(Foldable<decltype(xs)>{}, "");
+
+ _injection<0> f{};
+ ct_eq<999> s{};
+
+ // equivalence of size(xs) and length(xs)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::length(xs),
+ hana::size(xs)
+ ));
+
+ // equivalence of fold with fold_left and
+ // of reverse_fold with fold_right
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fold(xs, s, f),
+ hana::fold_left(xs, s, f)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::reverse_fold(xs, s, f),
+ hana::fold_right(xs, s, hana::flip(f))
+ ));
+
+ only_when_(hana::not_equal(hana::length(xs), hana::size_c<0>),
+ hana::make_lazy([](auto f, auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fold(xs, f),
+ hana::fold_left(xs, f)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::reverse_fold(xs, f),
+ hana::fold_right(xs, hana::flip(f))
+ ));
+ })(f, xs));
+
+ // equivalence of count(xs, val) and count_if(xs, equal.to(val))
+ struct not_there { };
+ BOOST_HANA_CHECK(hana::equal(
+ hana::count(xs, not_there{}),
+ hana::count_if(xs, equal.to(not_there{}))
+ ));
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::count(xs, value),
+ hana::count_if(xs, equal.to(value))
+ ));
+ }));
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestFoldable<P, when<Product<P>::value>>
+ : TestFoldable<P, laws>
+ {
+ template <typename Products>
+ TestFoldable(Products products) : TestFoldable<P, laws>{products} {
+ hana::for_each(products, [](auto p) {
+ _injection<0> f{};
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::unpack(p, f),
+ f(hana::first(p), hana::second(p))
+ ));
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestFoldable<S, when<Sequence<S>::value>>
+ : TestFoldable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <int i>
+ using ord = _constant<i>;
+
+ struct undefined { };
+
+ template <typename Xs>
+ TestFoldable(Xs xs) : TestFoldable<S, laws>{xs} {
+ _injection<0> f{};
+ auto z = x<999>{};
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // fold_left (with initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(), z, undefined{}),
+ z
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}), z, f),
+ f(z, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}), z, f),
+ f(f(z, x<1>{}), x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}, x<3>{}), z, f),
+ f(f(f(z, x<1>{}), x<2>{}), x<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), z, f),
+ f(f(f(f(z, x<1>{}), x<2>{}), x<3>{}), x<4>{})
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1), z, f),
+ f(z, 1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2'), z, f),
+ f(f(z, 1), '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2', 3.3), z, f),
+ f(f(f(z, 1), '2'), 3.3)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2', 3.3, 4.4f), z, f),
+ f(f(f(f(z, 1), '2'), 3.3), 4.4f)
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_left (without initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z), undefined{}),
+ z
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}), f),
+ f(z, x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}, x<3>{}), f),
+ f(f(z, x<2>{}), x<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}, x<3>{}, x<4>{}), f),
+ f(f(f(z, x<2>{}), x<3>{}), x<4>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_right (with initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(), z, undefined{}),
+ z
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}), z, f),
+ f(x<0>{}, z)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}), z, f),
+ f(x<0>{}, f(x<1>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}, x<2>{}), z, f),
+ f(x<0>{}, f(x<1>{}, f(x<2>{}, z)))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), z, f),
+ f(x<0>{}, f(x<1>{}, f(x<2>{}, f(x<3>{}, z))))
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1), z, f),
+ f(1, z)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2'), z, f),
+ f(1, f('2', z))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2', 3.3), z, f),
+ f(1, f('2', f(3.3, z)))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2', 3.3, 4.4f), z, f),
+ f(1, f('2', f(3.3, f(4.4f, z))))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_right (without initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(z), undefined{}),
+ z
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, z), f),
+ f(x<1>{}, z)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, x<2>{}, z), f),
+ f(x<1>{}, f(x<2>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, x<2>{}, x<3>{}, z), f),
+ f(x<1>{}, f(x<2>{}, f(x<3>{}, z)))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_left (with initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto s = x<999>{};
+ auto fp = hana::curry<2>(hana::flip(f));
+ constexpr auto mfold = monadic_fold_left<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(), s, undefined{}),
+ lift<M>(s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), s, f),
+ f(s, x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), s, f),
+ chain(f(s, x<1>{}), fp(x<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f),
+ chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f),
+ chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f),
+ chain(chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{})), fp(x<5>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_left (without initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto fp = hana::curry<2>(hana::flip(f));
+ constexpr auto mfold = monadic_fold_left<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), undefined{}),
+ lift<M>(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), f),
+ f(x<1>{}, x<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), f),
+ chain(f(x<1>{}, x<2>{}), fp(x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f),
+ chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f),
+ chain(chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{})), fp(x<5>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_right (with initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto s = x<999>{};
+ auto fp = hana::curry<2>(f);
+ // flipping `chain` makes the right associativity easier to see
+ auto chain = hana::flip(hana::chain);
+ constexpr auto mfold = monadic_fold_right<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(), s, undefined{}),
+ lift<M>(s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), s, f),
+ f(x<1>{}, s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), s, f),
+ chain(fp(x<1>{}), f(x<2>{}, s))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, s)))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, s))))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), chain(fp(x<4>{}), f(x<5>{}, s)))))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_right (without initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto fp = hana::curry<2>(f);
+ // flipping `chain` makes the right associativity easier to see
+ auto chain = hana::flip(hana::chain);
+ constexpr auto mfold = monadic_fold_right<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), undefined{}),
+ lift<M>(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), f),
+ f(x<1>{}, x<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), f),
+ chain(fp(x<1>{}), f(x<2>{}, x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, x<4>{})))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, x<5>{}))))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // length
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list()), size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{})), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{}, undefined{})), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{}, undefined{}, undefined{})), size_c<3>
+ ));
+
+ int i = 0; // non-constexpr
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(i, i)),
+ size_c<2>
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // maximum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{})),
+ ord<0>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{})),
+ ord<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{})),
+ ord<1>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{}, ord<2>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{}, ord<2>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<0>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<1>{}, ord<0>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<0>{}, ord<1>{})),
+ ord<2>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{}, ord<2>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{}, ord<2>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<0>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<3>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<1>{}, ord<3>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<3>{}, ord<1>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<3>{}, ord<0>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<2>{}, ord<0>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<0>{}, ord<2>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<0>{}, ord<1>{}, ord<2>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<2>{}, ord<3>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<3>{}, ord<1>{}, ord<2>{})),
+ ord<3>{}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0})),
+ int{0}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, long{1})),
+ long{1}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, long{0})),
+ int{1}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long{2})),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 0ll, long{2})),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{0})),
+ 2ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 1ll, long{0})),
+ int{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 0ll, long{1})),
+ int{2}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long{2}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 0ll, long{2}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{0}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{3}, short{0})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 1ll, long{3}, short{0})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 3ll, long{1}, short{0})),
+ 3ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 3ll, long{0}, short{1})),
+ 3ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 2ll, long{0}, short{1})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 0ll, long{2}, short{1})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 0ll, long{1}, short{2})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 2ll, long{3}, short{1})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 3ll, long{1}, short{2})),
+ 3ll
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long_c<2>)),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, long_c<1>, 2ll)),
+ 2ll
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // minimum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{}, ord<8>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{}, ord<8>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<6>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<9>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<7>{}, ord<9>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<9>{}, ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<9>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<8>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<6>{}, ord<8>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<6>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<8>{}, ord<9>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<9>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4})),
+ int{4}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4}, short{5})),
+ int{4}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{5}, short{4})),
+ short{4}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4}, short{5}, long{6})),
+ int{4}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{6}, long{8})),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{6})),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{7}, long{6})),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{6}, long{7})),
+ short{6}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{7}, long{8}, 9ll)),
+ int{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{6}, long{8}, 9ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{6}, 9ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{9}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{7}, long{9}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{9}, long{7}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{9}, long{6}, 7ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{8}, long{6}, 7ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{6}, long{8}, 7ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{6}, long{7}, 8ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{8}, long{9}, 7ll)),
+ int{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{9}, long{7}, 8ll)),
+ int{6}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{3}, short{4}, long_c<5>)),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(ord<33>{}, short{45}, long{46})),
+ ord<33>{}
+ ));
+ }
+
+
+ //////////////////////////////////////////////////////////////////
+ // count_if
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(), id), size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>), id), size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>), id), size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>, long_c<1>), id), size_c<3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>, long_c<0>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>, long_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>, long_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>, long_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>, long_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>, long_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>, long_c<0>), id), size_c<0>
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}), id), 0u
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}), id), 0u
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}, double{1}), id), 3u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}, double{0}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}, double{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}, double{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}, double{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}, double{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}, double{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}, double{0}), id), 0u
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) {
+ return x % 2 == 0;
+ };
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(), is_even), 0u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1), is_even), 0u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(2), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2, 3), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2, 3, 4), is_even), 2u
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // count
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(), undefined{}),
+ size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}), undefined{}),
+ size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}), ct_eq<0>{}),
+ size_c<1>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), undefined{}),
+ size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<0>{}),
+ size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<1>{}),
+ size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<0>{}), ct_eq<0>{}),
+ size_c<2>
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // product
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list()),
+ int_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>)),
+ int_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>)),
+ int_c<2 * 3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>)),
+ int_c<2 * 3 * 4>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>, int_c<5>)),
+ int_c<2 * 3 * 4 * 5>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<unsigned long>>(list()),
+ ulong_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<unsigned long>>(list(ulong_c<2>, ulong_c<3>, ulong_c<4>)),
+ ulong_c<2 * 3 * 4>
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2)),
+ 2
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3)),
+ 2 * 3
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3, 4)),
+ 2 * 3 * 4
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3, 4, 5)),
+ 2 * 3 * 4 * 5
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // sum
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list()),
+ int_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>)),
+ int_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>)),
+ int_c<1 + 2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>)),
+ int_c<1 + 2 + 3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>, int_c<4>)),
+ int_c<1 + 2 + 3 + 4>
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<unsigned long>>(list()),
+ ulong_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<unsigned long>>(list(ulong_c<1>, ulong_c<2>, ulong_c<3>)),
+ ulong_c<1 + 2 + 3>
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2)), 1 + 2
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2, 3)), 1 + 2 + 3
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2, 3, 4)), 1 + 2 + 3 + 4
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // unpack
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(), f),
+ f()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}), f),
+ f(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}), f),
+ f(x<0>{}, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}, x<2>{}), f),
+ f(x<0>{}, x<1>{}, x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), f),
+ f(x<0>{}, x<1>{}, x<2>{}, x<3>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_FOLDABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/functor.hpp b/src/boost/libs/hana/test/_include/laws/functor.hpp
new file mode 100644
index 000000000..d1ddbb4de
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/functor.hpp
@@ -0,0 +1,250 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_FUNCTOR_HPP
+#define BOOST_HANA_TEST_LAWS_FUNCTOR_HPP
+
+#include <boost/hana/adjust.hpp>
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/fill.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/replace.hpp>
+#include <boost/hana/replace_if.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestFunctor : TestFunctor<F, laws> {
+ using TestFunctor<F, laws>::TestFunctor;
+ };
+
+ template <typename F>
+ struct TestFunctor<F, laws> {
+ template <typename Xs, typename Elements>
+ TestFunctor(Xs xs, Elements elements) {
+ hana::for_each(xs, hana::capture(elements)([](auto elements, auto x) {
+ static_assert(Functor<decltype(x)>{}, "");
+
+ test::_injection<0> f{};
+ test::_injection<1> g{};
+
+ // identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(x, id),
+ x
+ ));
+
+ // composition
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(x, hana::compose(f, g)),
+ hana::transform(hana::transform(x, g), f)
+ ));
+
+ // method definitions in terms of transform/adjust_if
+ hana::for_each(elements, hana::capture(x, f, elements)(
+ [](auto x, auto f, auto elements, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::adjust(x, value, f),
+ hana::adjust_if(x, hana::equal.to(value), f)
+ ));
+
+ hana::for_each(elements, hana::capture(x, value)(
+ [](auto x, auto oldval, auto newval) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::replace(x, oldval, newval),
+ hana::replace_if(x, hana::equal.to(oldval), newval)
+ ));
+ }));
+ }));
+
+ auto pred = hana::always(true_c);
+ BOOST_HANA_CHECK(hana::equal(
+ hana::adjust_if(x, pred, f),
+ hana::transform(x, [=](auto z) {
+ return hana::eval_if(pred(z),
+ hana::make_lazy(f)(z),
+ hana::make_lazy(z)
+ );
+ })
+ ));
+
+ test::_constant<0> v{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::replace_if(x, pred, v),
+ hana::adjust_if(x, pred, hana::always(v))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fill(x, v),
+ hana::replace_if(x, hana::always(true_c), v)
+ ));
+
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestFunctor<S, when<Sequence<S>::value>>
+ : TestFunctor<S, laws>
+ {
+ struct undefined { };
+
+ template <typename Xs, typename Elements>
+ TestFunctor(Xs xs, Elements elements)
+ : TestFunctor<S, laws>{xs, elements}
+ {
+ using test::ct_eq;
+ using test::cx_eq;
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // replace_if
+ //////////////////////////////////////////////////////////////////
+ {
+ auto a = ct_eq<888>{};
+ auto b = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(), undefined{}, undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a), equal.to(a), b),
+ list(b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}), equal.to(a), b),
+ list(b, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, a), equal.to(a), b),
+ list(ct_eq<0>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, a), equal.to(a), b),
+ list(b, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), b),
+ list(b, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, a, ct_eq<2>{}), equal.to(a), b),
+ list(ct_eq<0>{}, b, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, a), equal.to(a), b),
+ list(ct_eq<0>{}, ct_eq<1>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, a), equal.to(a), b),
+ list(b, ct_eq<1>{}, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), equal.to(a), b),
+ list(b, ct_eq<1>{}, b, ct_eq<3>{}, b)
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // replace
+ //////////////////////////////////////////////////////////////////
+ {
+ auto a = ct_eq<888>{};
+ auto b = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(), undefined{}, undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}), a, undefined{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a), a, b),
+ list(b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}), a, undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}), a, b),
+ list(b, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, a), a, b),
+ list(ct_eq<0>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, a), a, b),
+ list(b, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), a, undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, ct_eq<2>{}), a, b),
+ list(b, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, a, ct_eq<2>{}), a, b),
+ list(ct_eq<0>{}, b, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, a), a, b),
+ list(ct_eq<0>{}, ct_eq<1>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, a), a, b),
+ list(b, ct_eq<1>{}, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), a, b),
+ list(b, ct_eq<1>{}, b, ct_eq<3>{}, b)
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_FUNCTOR_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/group.hpp b/src/boost/libs/hana/test/_include/laws/group.hpp
new file mode 100644
index 000000000..b9eeab776
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/group.hpp
@@ -0,0 +1,93 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_GROUP_HPP
+#define BOOST_HANA_TEST_LAWS_GROUP_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/concept/group.hpp>
+#include <boost/hana/lazy.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename G, typename = when<true>>
+ struct TestGroup : TestGroup<G, laws> {
+ using TestGroup<G, laws>::TestGroup;
+ };
+
+ template <typename G>
+ struct TestGroup<G, laws> {
+ template <typename Xs>
+ TestGroup(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Group<decltype(x)>{}, "");
+ });
+
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<G>(); // force adding zero<G>'s member function to pending temploid list
+#endif
+
+ foreach2(xs, [](auto x, auto y) {
+
+ // left inverse
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(x, hana::negate(x)),
+ zero<G>()
+ ));
+
+ // right inverse
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(hana::negate(x), x),
+ zero<G>()
+ ));
+
+ // default definition of minus
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(x, y),
+ hana::plus(x, hana::negate(y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(y, x),
+ hana::plus(y, hana::negate(x))
+ ));
+
+ // default definition of negate
+ BOOST_HANA_CHECK(hana::equal(
+ hana::negate(hana::negate(x)),
+ x
+ ));
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestGroup<C, when<Constant<C>::value>>
+ : TestGroup<C, laws>
+ {
+ template <typename Xs>
+ TestGroup(Xs xs) : TestGroup<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::negate(hana::value(x)),
+ hana::value(hana::negate(x))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(hana::value(x), hana::value(y)),
+ hana::value(hana::minus(x, y))
+ ));
+
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_GROUP_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/hashable.hpp b/src/boost/libs/hana/test/_include/laws/hashable.hpp
new file mode 100644
index 000000000..0fbd8f333
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/hashable.hpp
@@ -0,0 +1,60 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_HASHABLE_HPP
+#define BOOST_HANA_TEST_LAWS_HASHABLE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/hashable.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/hash.hpp>
+#include <boost/hana/if.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename G, typename = when<true>>
+ struct TestHashable : TestHashable<G, laws> {
+ using TestHashable<G, laws>::TestHashable;
+ };
+
+ template <typename H>
+ struct TestHashable<H, laws> {
+ template <typename Xs>
+ TestHashable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Hashable<decltype(x)>{}, "");
+ });
+
+ hana::for_each(xs, [&](auto const& x) {
+ hana::for_each(xs, [&](auto const& y) {
+ using X = hana::tag_of_t<decltype(x)>;
+ using Y = hana::tag_of_t<decltype(y)>;
+ constexpr bool comparable = !hana::is_default<
+ hana::equal_impl<X, Y>
+ >::value;
+
+ hana::if_(hana::bool_c<comparable>,
+ [](auto const& x, auto const& y) {
+ BOOST_HANA_CHECK(
+ hana::equal(x, y)
+ ^implies^
+ hana::equal(hana::hash(x), hana::hash(y))
+ );
+ },
+ [](auto...) { }
+ )(x, y);
+ });
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_HASHABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/iterable.hpp b/src/boost/libs/hana/test/_include/laws/iterable.hpp
new file mode 100644
index 000000000..d6d84c5ec
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/iterable.hpp
@@ -0,0 +1,195 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_ITERABLE_HPP
+#define BOOST_HANA_TEST_LAWS_ITERABLE_HPP
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/back.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/drop_front_exactly.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename It, typename = hana::when<true>>
+ struct TestIterable : TestIterable<It, laws> {
+ using TestIterable<It, laws>::TestIterable;
+ };
+
+ template <typename It>
+ struct TestIterable<It, laws> {
+ template <typename Xs>
+ TestIterable(Xs xs) {
+ hana::for_each(xs, [](auto xs) {
+ static_assert(Iterable<decltype(xs)>{}, "");
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::is_empty(xs) ^iff^ hana::is_empty(hana::to<tuple_tag>(xs))
+ );
+
+ only_when_(hana::not_(hana::is_empty(xs)), hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::front(xs),
+ hana::front(hana::to<tuple_tag>(xs))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::to<tuple_tag>(hana::drop_front_exactly(xs)),
+ hana::drop_front_exactly(hana::to<tuple_tag>(xs))
+ ));
+
+ // methods
+ // back(xs) == at(xs, length(xs)-1)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::back(xs),
+ hana::at(xs, hana::minus(hana::length(xs), hana::size_c<1>))
+ ));
+
+ })(xs));
+
+ // drop_front(xs, 0) == xs
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(xs, size_c<0>),
+ xs
+ ));
+
+ // at(xs, n) == front(drop_front(xs, n))
+ hana::for_each(hana::make_range(size_c<0>, hana::length(xs)),
+ hana::capture(xs)([](auto xs, auto n) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::at(xs, n),
+ hana::front(hana::drop_front(xs, n))
+ ));
+ }));
+
+ // Searchable
+ hana::eval_if(hana::is_empty(xs),
+ hana::make_lazy([](auto xs) {
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(xs, hana::always(true_c)))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(true_c)),
+ nothing
+ ));
+ })(xs),
+ hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, hana::always(true_c))
+ );
+ BOOST_HANA_CHECK(
+ hana::not_(hana::any_of(xs, hana::always(false_c)))
+ );
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(true_c)),
+ hana::just(hana::front(xs))
+ ));
+ })(xs)
+ );
+
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestIterable<S, when<Sequence<S>::value>>
+ : TestIterable<S, laws>
+ {
+ template <int i>
+ using x = ct_eq<i>;
+
+ template <int i = 0>
+ struct invalid { };
+
+ struct undefined { };
+
+ template <typename Xs>
+ TestIterable(Xs xs) : TestIterable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // front
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{}, invalid<>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{}, invalid<1>{}, invalid<2>{})),
+ x<0>{}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1, '2')), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1, '2', 3.3)), 1
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // back
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(x<0>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(invalid<0>{}, x<1>{})),
+ x<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(invalid<0>{}, invalid<1>{}, x<2>{})),
+ x<2>{}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1, '2')), '2'
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1, '2', 3.3)), 3.3
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_ITERABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/logical.hpp b/src/boost/libs/hana/test/_include/laws/logical.hpp
new file mode 100644
index 000000000..df9932766
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/logical.hpp
@@ -0,0 +1,137 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_LOGICAL_HPP
+#define BOOST_HANA_TEST_LAWS_LOGICAL_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/concept/logical.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename L, typename = when<true>>
+ struct TestLogical : TestLogical<L, laws> {
+ using TestLogical<L, laws>::TestLogical;
+ };
+
+ template <typename L>
+ struct TestLogical<L, laws> {
+ template <typename Xs, typename Pred, typename F>
+ static void for_each_such_that(Xs xs, Pred pred, F f) {
+ hana::for_each(xs, [&pred, &f](auto x) {
+ hana::eval_if(pred(x),
+ hana::make_lazy(f)(x),
+ [](auto) { }
+ );
+ });
+ }
+
+ template <typename Xs>
+ TestLogical(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Logical<decltype(x)>{}, "");
+ });
+
+ foreach3(xs, hana::capture(xs)([](auto xs, auto a, auto b, auto c) {
+ auto true_valued = [](auto x) {
+ return hana::if_(x, true_c, false_c);
+ };
+ auto false_valued = [](auto x) {
+ return hana::if_(x, false_c, true_c);
+ };
+
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::or_(b, c)),
+ hana::or_(hana::or_(a, b), c)
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::and_(b, c)),
+ hana::and_(hana::and_(a, b), c)
+ ));
+
+ // equivalence through commutativity
+ BOOST_HANA_CHECK(
+ hana::or_(a, b) ^iff^ hana::or_(b, a)
+ );
+ BOOST_HANA_CHECK(
+ hana::and_(a, b) ^iff^ hana::and_(b, a)
+ );
+
+ // absorption
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::and_(a, b)), a
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::or_(a, b)), a
+ ));
+
+ // left identity
+ TestLogical::for_each_such_that(xs, true_valued,
+ hana::capture(a)([](auto a, auto t) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(t, a), a
+ ));
+ }));
+ TestLogical::for_each_such_that(xs, false_valued,
+ hana::capture(a)([](auto a, auto f) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(f, a), a
+ ));
+ }));
+
+ // distributivity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::and_(b, c)),
+ hana::and_(hana::or_(a, b), hana::or_(a, c))
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::or_(b, c)),
+ hana::or_(hana::and_(a, b), hana::and_(a, c))
+ ));
+
+ // complements
+ BOOST_HANA_CHECK(true_valued(hana::or_(a, hana::not_(a))));
+ BOOST_HANA_CHECK(false_valued(hana::and_(a, hana::not_(a))));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestLogical<C, when<Constant<C>::value>>
+ : TestLogical<C, laws>
+ {
+ template <typename Xs>
+ TestLogical(Xs xs) : TestLogical<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::not_(x)),
+ hana::not_(hana::value(x))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::and_(x, y)),
+ hana::and_(hana::value(x), hana::value(y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::or_(x, y)),
+ hana::or_(hana::value(x), hana::value(y))
+ ));
+
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_LOGICAL_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monad.hpp b/src/boost/libs/hana/test/_include/laws/monad.hpp
new file mode 100644
index 000000000..25a23d417
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monad.hpp
@@ -0,0 +1,222 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_MONAD_HPP
+#define BOOST_HANA_TEST_LAWS_MONAD_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/monadic_compose.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonad : TestMonad<M, laws> {
+ using TestMonad<M, laws>::TestMonad;
+ };
+
+ template <typename M>
+ struct TestMonad<M, laws> {
+ // Xs are Monads over something
+ // XXs are Monads over Monads over something
+ template <typename Xs, typename XXs>
+ TestMonad(Xs xs, XXs xxs) {
+ hana::for_each(xs, [](auto m) {
+ static_assert(Monad<decltype(m)>{}, "");
+
+ auto f = hana::compose(lift<M>, test::_injection<0>{});
+ auto g = hana::compose(lift<M>, test::_injection<1>{});
+ auto h = hana::compose(lift<M>, test::_injection<2>{});
+ auto x = test::ct_eq<0>{};
+
+ //////////////////////////////////////////////////////////////
+ // Laws formulated with `monadic_compose`
+ //////////////////////////////////////////////////////////////
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(h, hana::monadic_compose(g, f))(x),
+ hana::monadic_compose(hana::monadic_compose(h, g), f)(x)
+ ));
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(lift<M>, f)(x),
+ f(x)
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(f, lift<M>)(x),
+ f(x)
+ ));
+
+ //////////////////////////////////////////////////////////////
+ // Laws formulated with `chain`
+ //
+ // This just provides us with some additional cross-checking,
+ // but the documentation does not mention those.
+ //////////////////////////////////////////////////////////////
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(hana::lift<M>(x), f),
+ f(x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, lift<M>),
+ m
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, [f, g](auto x) {
+ return hana::chain(f(x), g);
+ }),
+ hana::chain(hana::chain(m, f), g)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(m, f),
+ hana::chain(m, hana::compose(lift<M>, f))
+ ));
+
+ //////////////////////////////////////////////////////////////
+ // Consistency of method definitions
+ //////////////////////////////////////////////////////////////
+ // consistency of `chain`
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, f),
+ hana::flatten(hana::transform(m, f))
+ ));
+
+ // consistency of `monadic_compose`
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(f, g)(x),
+ hana::chain(g(x), f)
+ ));
+ });
+
+ // consistency of `flatten`
+ hana::for_each(xxs, [](auto mm) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::flatten(mm),
+ hana::chain(mm, hana::id)
+ ));
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestMonad<S, when<Sequence<S>::value>>
+ : TestMonad<S, laws>
+ {
+ template <typename Xs, typename XXs>
+ TestMonad(Xs xs, XXs xxs)
+ : TestMonad<S, laws>{xs, xxs}
+ {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // flatten
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(), list())),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(ct_eq<0>{}), list())),
+ list(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(), list(ct_eq<0>{}))),
+ list(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(ct_eq<0>{}), list(ct_eq<1>{}))),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(
+ list(ct_eq<0>{}, ct_eq<1>{}),
+ list(),
+ list(ct_eq<2>{}, ct_eq<3>{}),
+ list(ct_eq<4>{})
+ )),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+
+ // just make sure we don't double move; this happened in hana::tuple
+ hana::flatten(list(list(Tracked{1}, Tracked{2})));
+
+ //////////////////////////////////////////////////////////////////
+ // chain
+ //////////////////////////////////////////////////////////////////
+ {
+ test::_injection<0> f{};
+ auto g = hana::compose(list, f);
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(), g),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}), g),
+ list(f(ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}), f(ct_eq<4>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_compose
+ //////////////////////////////////////////////////////////////////
+ {
+ test::_injection<0> f{};
+ test::_injection<1> g{};
+
+ auto mf = [=](auto x) { return list(f(x), f(f(x))); };
+ auto mg = [=](auto x) { return list(g(x), g(g(x))); };
+
+ auto x = test::ct_eq<0>{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(mf, mg)(x),
+ list(f(g(x)), f(f(g(x))), f(g(g(x))), f(f(g(g(x)))))
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONAD_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monad_plus.hpp b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp
new file mode 100644
index 000000000..406320c91
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp
@@ -0,0 +1,616 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
+#define BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
+
+#include <boost/hana/append.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/cycle.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/prefix.hpp>
+#include <boost/hana/prepend.hpp>
+#include <boost/hana/remove.hpp>
+#include <boost/hana/remove_if.hpp>
+#include <boost/hana/replicate.hpp>
+#include <boost/hana/suffix.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonadPlus : TestMonadPlus<M, laws> {
+ using TestMonadPlus<M, laws>::TestMonadPlus;
+ };
+
+ template <typename M>
+ struct TestMonadPlus<M, laws> {
+ template <typename Xs, typename Predicates, typename Values>
+ TestMonadPlus(Xs xs, Predicates predicates, Values values) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ empty<M>(); // force adding empty<M>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, [](auto a) {
+ static_assert(MonadPlus<decltype(a)>{}, "");
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(hana::empty<M>(), a),
+ a
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(a, hana::empty<M>()),
+ a
+ ));
+
+ // absorption
+ auto f = hana::compose(lift<M>, test::_injection<0>{});
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(hana::empty<M>(), f),
+ hana::empty<M>()
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(a, hana::always(hana::empty<M>())),
+ hana::empty<M>()
+ ));
+
+ });
+
+ // associativity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(a, hana::concat(b, c)),
+ hana::concat(hana::concat(a, b), c)
+ ));
+ });
+
+ // Default method definitions
+ hana::for_each(xs, hana::capture(predicates, values)(
+ [](auto predicates, auto values, auto x) {
+
+ // remove_if(x, pred) == filter(x, negated pred)
+ hana::for_each(predicates, hana::capture(x)([](auto x, auto pred) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::remove_if(x, pred),
+ hana::filter(x, hana::compose(hana::not_, pred))
+ ));
+ }));
+
+ // remove(x, value) == remove_if(x, equal.to(value))
+ hana::for_each(values, hana::capture(x)([](auto x, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::remove(x, value),
+ hana::remove_if(x, hana::equal.to(value))
+ ));
+ }));
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestMonadPlus<S, when<Sequence<S>::value>>
+ : TestMonadPlus<S, laws>
+ {
+ template <int i>
+ using eq = test::ct_eq<i>;
+
+ struct undefined { };
+
+ template <typename Xs, typename Predicates, typename Values>
+ TestMonadPlus(Xs xs, Predicates predicates, Values values)
+ : TestMonadPlus<S, laws>{xs, predicates, values}
+ {
+ auto z = eq<999>{};
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // empty
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::empty<S>(), list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // concat
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list(eq<0>{})),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list(eq<0>{}, eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list()),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list(eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list(eq<1>{}, eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list()),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list(eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list(eq<2>{}, eq<3>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1), list()),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(), list(1)),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1), list('2')),
+ list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1, '2'), list(3.3)),
+ list(1, '2', 3.3)
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // filter
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z), not_equal.to(z)),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}), not_equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}, eq<3>{}), not_equal.to(z)),
+ list(eq<2>{}, eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z, eq<3>{}), not_equal.to(z)),
+ list(eq<1>{}, eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}, z), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z, z), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}, z), not_equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, z, eq<3>{}), not_equal.to(z)),
+ list(eq<3>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, z), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // prepend
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(), eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}, eq<2>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}, eq<2>{}, eq<3>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list(), 1),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list('2'), 1),
+ list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list('2', 3.3), 1),
+ list(1, '2', 3.3)
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // append
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(), eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(eq<0>{}), eq<1>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(eq<0>{}, eq<1>{}), eq<2>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(), 1), list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(1), '2'), list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(1, '2'), 3.3), list(1, '2', 3.3)
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // cycle
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<1>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<2>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<3>),
+ list()
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<1>),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<2>),
+ list(eq<0>{}, eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<3>),
+ list(eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<1>),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<2>),
+ list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<3>),
+ list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<1>),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<2>),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<3>),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // remove_if
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z), equal.to(z)),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}), equal.to(z)),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, eq<1>{}), equal.to(z)),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z), equal.to(z)),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}, eq<2>{}), equal.to(z)),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}, z), equal.to(z)),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z, eq<2>{}), equal.to(z)),
+ list(eq<0>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, eq<1>{}, eq<2>{}), equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z, eq<2>{}), equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z, z), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z, z), equal.to(z)),
+ list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // remove
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}), z),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, eq<1>{}), z),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}, z), z),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z, eq<2>{}), z),
+ list(eq<0>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, eq<1>{}, eq<2>{}), z),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z, eq<2>{}), z),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z, z), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z, z), z),
+ list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // replicate
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<0>),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<1>),
+ list(eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<2>),
+ list(eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<3>),
+ list(eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<4>),
+ list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<5>),
+ list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // prefix
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}), z),
+ list(z, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}), z),
+ list(z, eq<0>{}, z, eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
+ list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{})
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // suffix
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}), z),
+ list(eq<0>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}, z)
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monoid.hpp b/src/boost/libs/hana/test/_include/laws/monoid.hpp
new file mode 100644
index 000000000..d500992a0
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monoid.hpp
@@ -0,0 +1,86 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_MONOID_HPP
+#define BOOST_HANA_TEST_LAWS_MONOID_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/concept/monoid.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonoid : TestMonoid<M, laws> {
+ using TestMonoid<M, laws>::TestMonoid;
+ };
+
+ template <typename M>
+ struct TestMonoid<M, laws> {
+ template <typename Xs>
+ TestMonoid(Xs xs) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<M>(); // force adding zero<M>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto a) {
+ static_assert(Monoid<decltype(a)>{}, "");
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(zero<M>(), a),
+ a
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(a, zero<M>()),
+ a
+ ));
+
+ hana::for_each(xs,
+ hana::capture(xs, a)([](auto xs, auto a, auto b) {
+ hana::for_each(xs,
+ hana::capture(a, b)([](auto a, auto b, auto c) {
+ // associativity
+ BOOST_HANA_CHECK(equal(
+ hana::plus(a, hana::plus(b, c)),
+ hana::plus(hana::plus(a, b), c)
+ ));
+ }));
+ }));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestMonoid<C, when<Constant<C>::value>>
+ : TestMonoid<C, laws>
+ {
+ template <typename Xs>
+ TestMonoid(Xs xs) : TestMonoid<C, laws>{xs} {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(zero<C>()),
+ zero<typename C::value_type>()
+ ));
+
+ foreach2(xs, [](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(hana::value(x), hana::value(y)),
+ hana::value(hana::plus(x, y))
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONOID_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/orderable.hpp b/src/boost/libs/hana/test/_include/laws/orderable.hpp
new file mode 100644
index 000000000..f49ea7f8a
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/orderable.hpp
@@ -0,0 +1,182 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
+#define BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/greater.hpp>
+#include <boost/hana/greater_equal.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/less.hpp>
+#include <boost/hana/less_equal.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/ordering.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename T, typename = when<true>>
+ struct TestOrderable : TestOrderable<T, laws> {
+ using TestOrderable<T, laws>::TestOrderable;
+ };
+
+ template <typename T>
+ struct TestOrderable<T, laws> {
+ template <typename Xs>
+ TestOrderable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Orderable<decltype(x)>{}, "");
+ });
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // antisymmetry
+ BOOST_HANA_CHECK(
+ hana::and_(hana::less_equal(a, b), hana::less_equal(b, a))
+ ^implies^ hana::equal(a, b)
+ );
+
+ // totality
+ BOOST_HANA_CHECK(
+ hana::or_(hana::less_equal(a, b), hana::less_equal(b, a))
+ );
+
+ // other methods in terms of `less_equal`
+ BOOST_HANA_CHECK(
+ hana::less(a, b) ^iff^ hana::not_(hana::less_equal(b, a))
+ );
+
+ BOOST_HANA_CHECK(
+ hana::greater(a, b) ^iff^ hana::less(b, a)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::greater_equal(a, b) ^iff^ hana::not_(hana::less(a, b))
+ );
+
+ // less.than & al.
+ BOOST_HANA_CHECK(hana::less.than(a)(b) ^iff^ hana::less(b, a));
+ BOOST_HANA_CHECK(hana::greater.than(a)(b) ^iff^ hana::greater(b, a));
+ BOOST_HANA_CHECK(hana::less_equal.than(a)(b) ^iff^ hana::less_equal(b, a));
+ BOOST_HANA_CHECK(hana::greater_equal.than(a)(b) ^iff^ hana::greater_equal(b, a));
+
+ // ordering
+ _injection<0> f{}; // test::_injection is also monotonic
+ BOOST_HANA_CHECK(
+ hana::ordering(f)(a, b) ^iff^ hana::less(f(a), f(b))
+ );
+ });
+
+ // transitivity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(
+ hana::and_(hana::less_equal(a, b), hana::less_equal(b, c))
+ ^implies^ hana::less_equal(a, c)
+ );
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestOrderable<C, when<Constant<C>::value>>
+ : TestOrderable<C, laws>
+ {
+ template <typename Xs>
+ TestOrderable(Xs xs) : TestOrderable<C, laws>{xs} {
+ foreach2(xs, [](auto a, auto b) {
+
+ BOOST_HANA_CHECK(
+ hana::value(hana::less(a, b)) ^iff^
+ hana::less(hana::value(a), hana::value(b))
+ );
+
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestOrderable<P, when<Product<P>::value>>
+ : TestOrderable<P, laws>
+ {
+ template <typename Products>
+ TestOrderable(Products products)
+ : TestOrderable<P, laws>{products}
+ {
+ foreach2(products, [](auto x, auto y) {
+ BOOST_HANA_CHECK(
+ hana::less(x, y) ^iff^
+ hana::or_(
+ hana::less(hana::first(x), hana::first(y)),
+ hana::and_(
+ hana::equal(hana::first(x), hana::first(y)),
+ hana::less(hana::second(x), hana::second(y))
+ )
+ )
+ );
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestOrderable<S, when<Sequence<S>::value>>
+ : TestOrderable<S, laws>
+ {
+ struct invalid { };
+
+ template <typename Xs>
+ TestOrderable(Xs xs) : TestOrderable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // less
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(),
+ list()
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(),
+ list(invalid{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(invalid{}),
+ list()
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(ct_ord<0>{}),
+ list(ct_ord<7>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(ct_ord<1>{}),
+ list(ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(ct_ord<0>{}, ct_ord<1>{}, ct_ord<8>{}),
+ list(ct_ord<0>{}, ct_ord<1>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(ct_ord<0>{}, ct_ord<0>{}, ct_ord<8>{}),
+ list(ct_ord<0>{}, ct_ord<1>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/product.hpp b/src/boost/libs/hana/test/_include/laws/product.hpp
new file mode 100644
index 000000000..18e5a15d2
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/product.hpp
@@ -0,0 +1,46 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_PRODUCT_HPP
+#define BOOST_HANA_TEST_LAWS_PRODUCT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/second.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename P, typename = when<true>>
+ struct TestProduct : TestProduct<P, laws> {
+ using TestProduct<P, laws>::TestProduct;
+ };
+
+ template <typename P>
+ struct TestProduct<P, laws> {
+ template <typename Elements>
+ TestProduct(Elements elements) {
+ foreach2(elements, [](auto x, auto y) {
+ static_assert(Product<decltype(hana::make<P>(x, y))>{}, "");
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::first(hana::make<P>(x, y)),
+ x
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::second(hana::make<P>(x, y)),
+ y
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_PRODUCT_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/ring.hpp b/src/boost/libs/hana/test/_include/laws/ring.hpp
new file mode 100644
index 000000000..4afbca05c
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/ring.hpp
@@ -0,0 +1,125 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_RING_HPP
+#define BOOST_HANA_TEST_LAWS_RING_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/one.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/power.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename R, typename = when<true>>
+ struct TestRing : TestRing<R, laws> {
+ using TestRing<R, laws>::TestRing;
+ };
+
+ template <typename R>
+ struct TestRing<R, laws> {
+ template <typename Xs>
+ TestRing(Xs xs) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ one<R>(); // force adding one<R>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto x) {
+ static_assert(Ring<decltype(x)>{}, "");
+
+ foreach2(xs, hana::capture(x)([](auto x, auto y, auto z) {
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, hana::mult(y, z)),
+ hana::mult(hana::mult(x, y), z)
+ ));
+
+ // distributivity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, hana::plus(y, z)),
+ hana::plus(hana::mult(x, y), hana::mult(x, z))
+ ));
+ }));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, one<R>()), x
+ ));
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(one<R>(), x), x
+ ));
+
+ // power
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<0>),
+ one<R>()
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<1>),
+ x
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<2>),
+ hana::mult(x, x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<3>),
+ hana::mult(hana::mult(x, x), x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<4>),
+ hana::mult(hana::mult(hana::mult(x, x), x), x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<5>),
+ hana::mult(hana::mult(hana::mult(hana::mult(x, x), x), x), x)
+ ));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestRing<C, when<Constant<C>::value>>
+ : TestRing<C, laws>
+ {
+ template <typename Xs>
+ TestRing(Xs xs) : TestRing<C, laws>{xs} {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(one<C>()),
+ one<typename C::value_type>()
+ ));
+
+ foreach2(xs, [](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(hana::value(x), hana::value(y)),
+ hana::value(hana::mult(x, y))
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_RING_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/searchable.hpp b/src/boost/libs/hana/test/_include/laws/searchable.hpp
new file mode 100644
index 000000000..ae55b06eb
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/searchable.hpp
@@ -0,0 +1,611 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP
+#define BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP
+
+#include <boost/hana/all.hpp>
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/any.hpp>
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/is_a.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/is_disjoint.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/none.hpp>
+#include <boost/hana/none_of.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+#include <support/numeric.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename S, typename = when<true>>
+ struct TestSearchable : TestSearchable<S, laws> {
+ using TestSearchable<S, laws>::TestSearchable;
+ };
+
+ template <typename S>
+ struct TestSearchable<S, laws> {
+ template <typename Searchables, typename Keys>
+ TestSearchable(Searchables searchables, Keys keys) {
+ hana::for_each(searchables, [](auto xs) {
+ static_assert(Searchable<decltype(xs)>{}, "");
+ });
+
+ auto predicates = hana::concat(
+ hana::to_tuple(hana::transform(keys, equal.to)),
+ hana::make_tuple(
+ hana::always(false_c),
+ hana::always(true_c)
+ )
+ );
+
+ hana::for_each(searchables, hana::capture(searchables, keys, predicates)(
+ [](auto searchables, auto keys, auto predicates, auto xs) {
+ hana::for_each(predicates, hana::capture(xs)(
+ [](auto xs, auto p) {
+ // any_of(xs, p) <=> !all_of(xs, negated p)
+ // <=> !none_of(xs, p)
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, p) ^iff^
+ hana::not_(hana::all_of(xs, hana::compose(not_, p)))
+ );
+
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, p) ^iff^
+ hana::not_(hana::none_of(xs, p))
+ );
+ }));
+
+ // any(xs) <=> any_of(xs, id)
+ // all(xs) <=> all_of(xs, id)
+ // none(xs) <=> none_of(xs, id)
+ auto all_logicals = hana::all_of(xs, [](auto x) {
+ return hana::bool_c<hana::Logical<decltype(x)>::value>;
+ });
+ only_when_(all_logicals, hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(
+ hana::any(xs) ^iff^ hana::any_of(xs, id)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::all(xs) ^iff^ hana::all_of(xs, hana::id)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::none(xs) ^iff^ hana::none_of(xs, hana::id)
+ );
+ })(xs));
+
+ // find_if(xs, always(false_c)) == nothing
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(hana::false_c)),
+ hana::nothing
+ ));
+
+ hana::for_each(searchables, hana::capture(xs)([](auto xs, auto ys) {
+ // is_subset(xs, ys) <=> all_of(xs, [](auto x) { return contains(ys, x); })
+ BOOST_HANA_CHECK(
+ hana::is_subset(xs, ys) ^iff^
+ hana::all_of(xs, hana::partial(hana::contains, ys))
+ );
+
+ // is_disjoint(xs, ys) <=> none_of(xs, [](auto x) { return contains(ys, x); })
+ BOOST_HANA_CHECK(
+ hana::is_disjoint(xs, ys) ^iff^
+ hana::none_of(xs, hana::partial(hana::contains, ys))
+ );
+ }));
+
+ hana::for_each(keys, hana::capture(xs)([](auto xs, auto key) {
+ // find(xs, x) == find_if(xs, [](auto y) { return y == x; })
+ BOOST_HANA_CHECK(hana::equal(
+ hana::find(xs, key),
+ hana::find_if(xs, hana::equal.to(key))
+ ));
+
+ // contains(xs, x) <=> any_of(xs, [](auto y) { return y == x; })
+ BOOST_HANA_CHECK(
+ hana::contains(xs, key) ^iff^
+ hana::any_of(xs, hana::equal.to(key))
+ );
+
+ only_when_(hana::contains(xs, key),
+ hana::make_lazy([](auto xs, auto key) {
+ // at_key(xs, key) == find(xs, key).value()
+ BOOST_HANA_CHECK(hana::equal(
+ hana::at_key(xs, key),
+ hana::find(xs, key).value()
+ ));
+ })(xs, key)
+ );
+ }));
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestSearchable<S, when<Sequence<S>::value>>
+ : TestSearchable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <int = 0>
+ struct invalid { };
+
+ struct undefined { };
+
+ template <typename Xs, typename Keys>
+ TestSearchable(Xs xs, Keys keys)
+ : TestSearchable<S, laws>{xs, keys}
+ {
+ constexpr auto list = make<S>;
+
+ BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) {
+ return x % 2 == 0;
+ };
+
+ auto c = numeric; // a minimal comparable
+ auto logical = numeric;
+
+ //////////////////////////////////////////////////////////////////
+ // any_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(), equal.to(x<9>{})))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}), equal.to(x<0>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, invalid<1>{}), equal.to(x<0>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<1>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(), invalid<>{}))
+ );
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(c(0)), equal.to(c(0)))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(c(0)), equal.to(c(1))))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(1), is_even))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(2), is_even)
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(1, 2), is_even)
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(1, 3), is_even))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(1, 3, 4), is_even)
+ );
+
+ //////////////////////////////////////////////////////////////////
+ // any
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any(list())));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::any(list(logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any(list(logical(false)))));
+
+
+ //////////////////////////////////////////////////////////////////
+ // all_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(
+ all_of(list(), invalid<>{})
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ all_of(list(c(0)), equal.to(c(0)))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ not_(all_of(list(c(0)), equal.to(c(1))))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(not_(
+ all_of(list(c(0), c(1)), equal.to(c(0)))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(
+ all_of(list(c(0), c(0)), equal.to(c(0)))
+ );
+
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2, 4), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3, 4), is_even)));
+
+
+ //////////////////////////////////////////////////////////////////
+ // all
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(all(list()));
+ BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(false)))));
+ BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true), logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(true), logical(false)))));
+
+ //////////////////////////////////////////////////////////////////
+ // none_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(none_of(list(), invalid<>{}));
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(c(0)), equal.to(c(1))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(c(0)), equal.to(c(0)))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1, 3), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 3, 4), is_even)));
+
+
+ //////////////////////////////////////////////////////////////////
+ // none
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(none(list()));
+ BOOST_HANA_CONSTEXPR_CHECK(none(list(logical(false))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none(list(logical(true)))));
+
+ //////////////////////////////////////////////////////////////////
+ // find_if
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(), equal.to(x<9>{})),
+ nothing
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, invalid<1>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+
+ // Make sure find_if works with an lvalue sequence. hana::tuple
+ // used to have a bug that broke this.
+ auto const const_lvalue = list(x<0>{}, x<1>{}, x<2>{});
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(const_lvalue, equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+
+ auto lvalue = list(x<0>{}, x<1>{}, x<2>{});
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(lvalue, equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // find
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(), invalid<>{}),
+ nothing
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}), x<0>{}),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, invalid<1>{}), x<0>{}),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, invalid<1>{}, invalid<2>{}), x<0>{}),
+ just(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}), x<1>{}),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, invalid<2>{}), x<1>{}),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), x<1>{}),
+ just(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}, nothing), x<2>{}),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), x<2>{}),
+ just(x<2>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // at_key
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}), x<0>{}),
+ x<0>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}), x<0>{}),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}), x<1>{}),
+ x<1>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<0>{}),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<1>{}),
+ x<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}),
+ x<2>{}
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // contains
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(not_(
+ contains(list(), undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(not_(
+ contains(list(x<0>{}), x<999>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}), x<0>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}, x<1>{}), x<1>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}, x<1>{}, x<3>{}), x<3>{})
+ );
+
+ BOOST_HANA_CONSTEXPR_CHECK(contains(list(c(0)), c(0)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(contains(list(c(0)), c(1))));
+
+ // infix application
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}, x<1>{}) ^contains^ x<1>{}
+ );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // in
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTEXPR_CHECK(c(0) ^in^ list(c(0)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(c(1) ^in^ list(c(0))));
+
+ //////////////////////////////////////////////////////////////////
+ // is_subset
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(is_subset(
+ list(), list(undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(not_(is_subset(
+ list(undefined{}), list()
+ )));
+
+ BOOST_HANA_CONSTEXPR_CHECK(is_subset(
+ list(c(0)), list(c(0))
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(is_subset(
+ list(c(0)), list(c(0), c(1))
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(not_(is_subset(
+ list(c(0)), list(c(1))
+ )));
+
+ // infix application
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}) ^is_subset^ list(x<1>{}, x<0>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}, x<1>{}) ^is_subset^ list(x<1>{}, x<0>{})
+ );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // is_disjoint
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(),
+ list(undefined{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<0>{}),
+ list(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<1>{}),
+ list(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}),
+ list(x<0>{})
+ )));
+
+
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}),
+ list(x<0>{}, x<1>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<1>{}, x<0>{}),
+ list(x<0>{}, x<1>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<1>{}, x<2>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<2>{}, x<3>{})
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/sequence.hpp b/src/boost/libs/hana/test/_include/laws/sequence.hpp
new file mode 100644
index 000000000..cc04590ea
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/sequence.hpp
@@ -0,0 +1,133 @@
+// 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)
+
+#ifndef BOOST_HANA_TEST_LAWS_SEQUENCE_HPP
+#define BOOST_HANA_TEST_LAWS_SEQUENCE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+#include <support/minimal_product.hpp>
+#include <support/seq.hpp>
+
+#include <type_traits>
+#include <vector>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename S, typename = when<true>>
+ struct TestSequence : TestSequence<S, laws> {
+ using TestSequence<S, laws>::TestSequence;
+ };
+
+ template <typename S>
+ struct TestSequence<S, laws> {
+ template <int i>
+ using eq = integer<i,
+ Policy::Comparable
+ | Policy::Constant
+ >;
+
+ template <int i>
+ using cx_eq = integer<i,
+ Policy::Comparable
+ | Policy::Constexpr
+ >;
+
+ template <int i>
+ using ord = integer<i,
+ Policy::Orderable
+ | Policy::Constant
+ >;
+
+ struct undefined { };
+
+ TestSequence() {
+ constexpr auto list = make<S>; (void)list;
+ constexpr auto foldable = ::seq; (void)foldable;
+
+ //////////////////////////////////////////////////////////////////
+ // Check for Sequence<...>
+ //////////////////////////////////////////////////////////////////
+ static_assert(Sequence<decltype(list())>{}, "");
+ static_assert(Sequence<decltype(list(1))>{}, "");
+ static_assert(Sequence<decltype(list(1, '2'))>{}, "");
+ static_assert(Sequence<decltype(list(1, '2', 3.4))>{}, "");
+
+ //////////////////////////////////////////////////////////////////
+ // Check for basic tag consistency
+ //////////////////////////////////////////////////////////////////
+ struct Random;
+ static_assert(std::is_same<tag_of_t<decltype(list())>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1))>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1, '2'))>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1, '2', 3.3))>, S>{}, "");
+ static_assert(!std::is_same<tag_of_t<Random>, S>{}, "");
+
+ //////////////////////////////////////////////////////////////////
+ // Foldable -> Sequence conversion
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{})),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // make (tautological given our definition of `list`)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}, eq<2>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_SEQUENCE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/templates/seq.hpp b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp
new file mode 100644
index 000000000..72438fc50
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp
@@ -0,0 +1,132 @@
+// 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 <boost/hana/bool.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/applicative.hpp>
+#include <laws/base.hpp>
+#include <laws/comparable.hpp>
+#include <laws/foldable.hpp>
+#include <laws/functor.hpp>
+#include <laws/iterable.hpp>
+#include <laws/monad.hpp>
+#include <laws/monad_plus.hpp>
+#include <laws/orderable.hpp>
+#include <laws/searchable.hpp>
+#include <laws/sequence.hpp>
+#include <support/seq.hpp>
+namespace hana = boost::hana;
+using hana::test::ct_eq;
+using hana::test::ct_ord;
+
+
+int main() {
+ auto eqs = hana::make_tuple(
+ ::seq()
+ , ::seq(ct_eq<0>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ );
+ (void)eqs;
+
+ auto nested_eqs = hana::make_tuple(
+ ::seq()
+ , ::seq(
+ ::seq(ct_eq<0>{}))
+ , ::seq(
+ ::seq(ct_eq<0>{}),
+ ::seq(ct_eq<1>{}, ct_eq<2>{}))
+ , ::seq(
+ ::seq(ct_eq<0>{}),
+ ::seq(ct_eq<1>{}, ct_eq<2>{}),
+ ::seq(ct_eq<3>{}, ct_eq<4>{}))
+ );
+ (void)nested_eqs;
+
+ auto eq_keys = hana::make_tuple(ct_eq<0>{}, ct_eq<3>{}, ct_eq<10>{});
+ (void)eq_keys;
+
+ auto predicates = hana::make_tuple(
+ hana::equal.to(ct_eq<0>{}), hana::equal.to(ct_eq<3>{}), hana::equal.to(ct_eq<10>{}),
+ hana::always(hana::true_c), hana::always(hana::false_c)
+ );
+ (void)predicates;
+
+ auto ords = hana::make_tuple(
+ ::seq()
+ , ::seq(ct_ord<0>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, ct_ord<3>{})
+ );
+ (void)ords;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable, Orderable
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_ORDERABLE
+ hana::test::TestComparable<::Seq>{eqs};
+ hana::test::TestOrderable<::Seq>{ords};
+#endif
+
+#ifdef BOOST_HANA_TEST_ITERABLE
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ hana::test::TestFoldable<::Seq>{eqs};
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ {
+ hana::test::TestIterable<::Seq>{eqs};
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_SEARCHABLE
+ {
+ hana::test::TestSearchable<::Seq>{eqs, eq_keys};
+
+ auto bools = hana::make_tuple(
+ ::seq(hana::true_c)
+ , ::seq(hana::false_c)
+ , ::seq(hana::true_c, hana::true_c)
+ , ::seq(hana::true_c, hana::false_c)
+ , ::seq(hana::false_c, hana::true_c)
+ , ::seq(hana::false_c, hana::false_c)
+ );
+ hana::test::TestSearchable<::Seq>{bools, hana::make_tuple(hana::true_c, hana::false_c)};
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor, Applicative, Monad
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_MONAD
+ hana::test::TestFunctor<::Seq>{eqs, eq_keys};
+ hana::test::TestApplicative<::Seq>{eqs};
+ hana::test::TestMonad<::Seq>{eqs, nested_eqs};
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_MONAD_PLUS
+ hana::test::TestMonadPlus<::Seq>{eqs, predicates, eq_keys};
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_SEQUENCE
+ hana::test::TestSequence<::Seq>{};
+#endif
+}
diff --git a/src/boost/libs/hana/test/_include/support/cnumeric.hpp b/src/boost/libs/hana/test/_include/support/cnumeric.hpp
new file mode 100644
index 000000000..51575a40f
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/cnumeric.hpp
@@ -0,0 +1,66 @@
+// 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)
+
+#ifndef TEST_SUPPORT_CNUMERIC_HPP
+#define TEST_SUPPORT_CNUMERIC_HPP
+
+#include <boost/hana/concept/integral_constant.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/less.hpp>
+
+
+template <typename T>
+struct CNumeric { using value_type = T; };
+
+template <typename T, T v>
+struct cnumeric_t {
+ static constexpr T value = v;
+ using hana_tag = CNumeric<T>;
+ constexpr operator T() const { return value; }
+};
+
+template <typename T, T v>
+constexpr cnumeric_t<T, v> cnumeric{};
+
+template <typename T, T v>
+constexpr cnumeric_t<T, v> make_cnumeric() { return {}; }
+
+namespace boost { namespace hana {
+ // Constant and IntegralConstant
+ template <typename T>
+ struct IntegralConstant<CNumeric<T>> {
+ static constexpr bool value = true;
+ };
+
+ template <typename T, typename C>
+ struct to_impl<CNumeric<T>, C, when<
+ hana::IntegralConstant<C>::value
+ >>
+ : embedding<is_embedded<typename C::value_type, T>::value>
+ {
+ template <typename N>
+ static constexpr auto apply(N const&)
+ { return cnumeric<T, N::value>; }
+ };
+
+ // Comparable
+ template <typename T, typename U>
+ struct equal_impl<CNumeric<T>, CNumeric<U>> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const&, Y const&)
+ { return cnumeric<bool, X::value == Y::value>; }
+ };
+
+ // Orderable
+ template <typename T, typename U>
+ struct less_impl<CNumeric<T>, CNumeric<U>> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X const&, Y const&)
+ { return cnumeric<bool, (X::value < Y::value)>; }
+ };
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_CNUMERIC_HPP
diff --git a/src/boost/libs/hana/test/_include/support/constexpr_move_only.hpp b/src/boost/libs/hana/test/_include/support/constexpr_move_only.hpp
new file mode 100644
index 000000000..bdc234afe
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/constexpr_move_only.hpp
@@ -0,0 +1,41 @@
+// 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)
+
+#ifndef TEST_SUPPORT_CONSTEXPR_MOVE_ONLY_HPP
+#define TEST_SUPPORT_CONSTEXPR_MOVE_ONLY_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/fwd/hash.hpp>
+#include <boost/hana/type.hpp>
+
+#include <utility>
+
+
+// A move-only type that's also a literal type. It is also Comparable and
+// Hashable so it can be used in associative containers.
+template <int i>
+struct ConstexprMoveOnly {
+ constexpr ConstexprMoveOnly() { }
+ constexpr ConstexprMoveOnly(ConstexprMoveOnly const&) = delete;
+ constexpr ConstexprMoveOnly& operator=(ConstexprMoveOnly const&) = delete;
+ constexpr ConstexprMoveOnly(ConstexprMoveOnly&&) { }
+};
+
+template <int i, int j>
+constexpr auto operator==(ConstexprMoveOnly<i> const&, ConstexprMoveOnly<j> const&)
+{ return boost::hana::bool_c<i == j>; }
+
+template <int i, int j>
+constexpr auto operator!=(ConstexprMoveOnly<i> const&, ConstexprMoveOnly<j> const&)
+{ return boost::hana::bool_c<i != j>; }
+
+namespace boost { namespace hana {
+ template <int i>
+ struct hash_impl<ConstexprMoveOnly<i>> {
+ static constexpr auto apply(ConstexprMoveOnly<i> const&)
+ { return hana::type_c<ConstexprMoveOnly<i>>; };
+ };
+}}
+
+#endif // !TEST_SUPPORT_CONSTEXPR_MOVE_ONLY_HPP
diff --git a/src/boost/libs/hana/test/_include/support/counter.hpp b/src/boost/libs/hana/test/_include/support/counter.hpp
new file mode 100644
index 000000000..4640363d7
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/counter.hpp
@@ -0,0 +1,56 @@
+// Copyright Louis Dionne 2013-2017
+// Copyright Jason Rice 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)
+
+#ifndef TEST_SUPPORT_COUNTER_HPP
+#define TEST_SUPPORT_COUNTER_HPP
+
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/concept/iterable.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+
+// Counter - an infinite iterable for the masses
+
+struct Counter_tag { };
+
+template <std::size_t N = 0>
+struct Counter {
+ using hana_tag = Counter_tag;
+ static constexpr std::size_t value = N;
+};
+
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<Counter_tag> {
+ template <typename T, typename N>
+ static constexpr decltype(auto) apply(T, N) {
+ return hana::size_c<T::value + N::value>;
+ }
+ };
+
+ template <>
+ struct drop_front_impl<Counter_tag> {
+ template <typename T, typename N>
+ static constexpr auto apply(T, N) {
+ return Counter<T::value + N::value>{};
+ }
+ };
+
+ template <>
+ struct is_empty_impl<Counter_tag> {
+ template <typename Xs>
+ static constexpr auto apply(Xs)
+ -> hana::false_
+ { return {}; }
+ };
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_COUNTER_HPP
diff --git a/src/boost/libs/hana/test/_include/support/equivalence_class.hpp b/src/boost/libs/hana/test/_include/support/equivalence_class.hpp
new file mode 100644
index 000000000..c5e8d72e6
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/equivalence_class.hpp
@@ -0,0 +1,34 @@
+// 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)
+
+#ifndef TEST_SUPPORT_EQUIVALENCE_CLASS_HPP
+#define TEST_SUPPORT_EQUIVALENCE_CLASS_HPP
+
+#include <boost/hana/fwd/equal.hpp>
+
+
+struct EquivalenceClass { };
+
+template <typename Token, typename T>
+struct equivalence_class_impl {
+ Token equivalence_class;
+ T unwrap;
+ using hana_tag = EquivalenceClass;
+};
+
+template <typename Token, typename X>
+constexpr equivalence_class_impl<Token, X> equivalence_class(Token token, X x) {
+ return {token, x};
+}
+
+namespace boost { namespace hana {
+ template <>
+ struct equal_impl<EquivalenceClass, EquivalenceClass> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return hana::equal(x.equivalence_class, y.equivalence_class); }
+ };
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_EQUIVALENCE_CLASS_HPP
diff --git a/src/boost/libs/hana/test/_include/support/identity.hpp b/src/boost/libs/hana/test/_include/support/identity.hpp
new file mode 100644
index 000000000..c6799cbe8
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/identity.hpp
@@ -0,0 +1,159 @@
+// 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)
+
+#ifndef TEST_SUPPORT_IDENTITY_HPP
+#define TEST_SUPPORT_IDENTITY_HPP
+
+#include <boost/hana/chain.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/adjust_if.hpp>
+#include <boost/hana/fwd/ap.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/flatten.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <type_traits>
+
+
+struct Identity;
+
+template <typename T>
+struct identity_t {
+ T value;
+ using hana_tag = Identity;
+};
+
+struct make_identity {
+ template <typename T>
+ constexpr identity_t<typename std::decay<T>::type> operator()(T&& t) const {
+ return {static_cast<T&&>(t)};
+ }
+};
+
+constexpr make_identity identity{};
+
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<Identity, Identity> {
+ template <typename Id1, typename Id2>
+ static constexpr auto apply(Id1 x, Id2 y)
+ { return hana::equal(x.value, y.value); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<Identity, Identity> {
+ template <typename Id1, typename Id2>
+ static constexpr auto apply(Id1 x, Id2 y)
+ { return hana::less(x.value, y.value); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //
+ // Define either one to select which MCD is used:
+ // BOOST_HANA_TEST_FUNCTOR_TRANSFORM_MCD
+ // BOOST_HANA_TEST_FUNCTOR_ADJUST_MCD_MCD
+ //
+ // If neither is defined, the MCD used is unspecified.
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_FUNCTOR_TRANSFORM_MCD
+ template <>
+ struct transform_impl<Identity> {
+ template <typename Id, typename F>
+ static constexpr auto apply(Id self, F f)
+ { return ::identity(f(self.value)); }
+ };
+#else
+ template <>
+ struct adjust_if_impl<Identity> {
+ struct get_value {
+ template <typename T>
+ constexpr auto operator()(T t) const { return t.value; }
+ };
+
+ template <typename Id, typename P, typename F>
+ static constexpr auto apply(Id self, P p, F f) {
+ auto x = hana::eval_if(p(self.value),
+ hana::make_lazy(hana::compose(f, get_value{}))(self),
+ hana::make_lazy(get_value{})(self)
+ );
+ return ::identity(x);
+ }
+ };
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //
+ // Define either one to select which MCD is used:
+ // BOOST_HANA_TEST_APPLICATIVE_FULL_MCD
+ // BOOST_HANA_TEST_APPLICATIVE_MONAD_MCD
+ //
+ // If neither is defined, the MCD used is unspecified.
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<Identity> {
+ template <typename X>
+ static constexpr auto apply(X x)
+ { return ::identity(x); }
+ };
+#ifdef BOOST_HANA_TEST_APPLICATIVE_FULL_MCD
+ template <>
+ struct ap_impl<Identity> {
+ template <typename F, typename X>
+ static constexpr auto apply(F f, X x)
+ { return ::identity(f.value(x.value)); }
+ };
+#else
+ template <>
+ struct ap_impl<Identity> {
+ template <typename F, typename X>
+ static constexpr decltype(auto) apply(F&& f, X&& x) {
+ return hana::chain(
+ static_cast<F&&>(f),
+ hana::partial(hana::transform, static_cast<X&&>(x))
+ );
+ }
+ };
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //
+ // Define either one to select which MCD is used:
+ // BOOST_HANA_TEST_MONAD_FLATTEN_MCD
+ // BOOST_HANA_TEST_MONAD_CHAIN_MCD
+ //
+ // If neither is defined, the MCD used is unspecified.
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_MONAD_FLATTEN_MCD
+ template <>
+ struct flatten_impl<Identity> {
+ template <typename Id>
+ static constexpr auto apply(Id self)
+ { return self.value; }
+ };
+#else
+ template <>
+ struct chain_impl<Identity> {
+ template <typename X, typename F>
+ static constexpr auto apply(X x, F f)
+ { return f(x.value); }
+ };
+#endif
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_IDENTITY_HPP
diff --git a/src/boost/libs/hana/test/_include/support/minimal_product.hpp b/src/boost/libs/hana/test/_include/support/minimal_product.hpp
new file mode 100644
index 000000000..1fe39f786
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/minimal_product.hpp
@@ -0,0 +1,61 @@
+// 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)
+
+#ifndef TEST_SUPPORT_MINIMAL_PRODUCT_HPP
+#define TEST_SUPPORT_MINIMAL_PRODUCT_HPP
+
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/first.hpp>
+#include <boost/hana/fwd/second.hpp>
+
+#include <type_traits>
+
+
+struct MinimalProduct;
+
+template <typename X, typename Y>
+struct product_t {
+ X fst;
+ Y snd;
+ using hana_tag = MinimalProduct;
+};
+
+struct make_minimal_product {
+ template <typename T, typename U>
+ constexpr product_t<typename std::decay<T>::type,
+ typename std::decay<U>::type>
+ operator()(T&& t, U&& u) const {
+ return {static_cast<T&&>(t), static_cast<U&&>(u)};
+ }
+};
+
+constexpr make_minimal_product minimal_product{};
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Product
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<MinimalProduct> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return ::minimal_product(x, y); }
+ };
+
+ template <>
+ struct first_impl<MinimalProduct> {
+ template <typename P>
+ static constexpr decltype(auto) apply(P&& p)
+ { return p.fst; }
+ };
+
+ template <>
+ struct second_impl<MinimalProduct> {
+ template <typename P>
+ static constexpr decltype(auto) apply(P&& p)
+ { return p.snd; }
+ };
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_MINIMAL_PRODUCT_HPP
diff --git a/src/boost/libs/hana/test/_include/support/numeric.hpp b/src/boost/libs/hana/test/_include/support/numeric.hpp
new file mode 100644
index 000000000..2aebe7664
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/numeric.hpp
@@ -0,0 +1,175 @@
+// 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)
+
+#ifndef TEST_SUPPORT_NUMERIC_HPP
+#define TEST_SUPPORT_NUMERIC_HPP
+
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/eval.hpp>
+#include <boost/hana/fwd/div.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/eval_if.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/fwd/minus.hpp>
+#include <boost/hana/fwd/mod.hpp>
+#include <boost/hana/fwd/mult.hpp>
+#include <boost/hana/fwd/negate.hpp>
+#include <boost/hana/fwd/not.hpp>
+#include <boost/hana/fwd/one.hpp>
+#include <boost/hana/fwd/plus.hpp>
+#include <boost/hana/fwd/while.hpp>
+#include <boost/hana/fwd/zero.hpp>
+
+
+struct numeric_type {
+ constexpr explicit numeric_type(int v) : value(v) { }
+ int value;
+ constexpr operator int() const { return value; }
+};
+
+using Numeric = boost::hana::tag_of_t<numeric_type>;
+
+struct numeric_t {
+ constexpr numeric_type operator()(int x) const {
+ return numeric_type{x};
+ }
+};
+constexpr numeric_t numeric{};
+
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value == y.value); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct less_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y) {
+ // Workaround a _weird_ GCC bug:
+ // error: parse error in template argument list
+ // bool cmp = (x.value < y.value);
+ // ^
+ int xv = x.value, yv = y.value;
+ return numeric(xv < yv);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Logical
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct eval_if_impl<Numeric> {
+ template <typename C, typename T, typename E>
+ static constexpr auto apply(C const& c, T&& t, E&& e) {
+ return c.value ? hana::eval(static_cast<T&&>(t))
+ : hana::eval(static_cast<E&&>(e));
+ }
+ };
+
+ template <>
+ struct not_impl<Numeric> {
+ template <typename X>
+ static constexpr auto apply(X x)
+ { return numeric(!x.value); }
+ };
+
+ template <>
+ struct while_impl<Numeric> {
+ template <typename Pred, typename State, typename F>
+ static constexpr auto apply(Pred pred, State state, F f)
+ -> decltype(true ? f(state) : state)
+ {
+ if (pred(state))
+ return hana::while_(pred, f(state), f);
+ else
+ return state;
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monoid
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct plus_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value + y.value); }
+ };
+
+ template <>
+ struct zero_impl<Numeric> {
+ static constexpr auto apply()
+ { return numeric(0); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Group
+ //
+ // Define either one to select which MCD is used:
+ // BOOST_HANA_TEST_GROUP_NEGATE_MCD
+ // BOOST_HANA_TEST_GROUP_MINUS_MCD
+ //
+ // If neither is defined, the MCD used is unspecified.
+ //////////////////////////////////////////////////////////////////////////
+#if defined(BOOST_HANA_TEST_GROUP_NEGATE_MCD)
+ template <>
+ struct negate_impl<Numeric> {
+ template <typename X>
+ static constexpr auto apply(X x)
+ { return numeric(-x.value); }
+ };
+#else
+ template <>
+ struct minus_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value - y.value); }
+ };
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Ring
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct mult_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value * y.value); }
+ };
+
+ template <>
+ struct one_impl<Numeric> {
+ static constexpr auto apply()
+ { return numeric(1); }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // EuclideanRing
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct div_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value / y.value); }
+ };
+
+ template <>
+ struct mod_impl<Numeric, Numeric> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y)
+ { return numeric(x.value % y.value); }
+ };
+}} // end namespace boost::hana
+
+#endif //! TEST_SUPPORT_NUMERIC_HPP
diff --git a/src/boost/libs/hana/test/_include/support/seq.hpp b/src/boost/libs/hana/test/_include/support/seq.hpp
new file mode 100644
index 000000000..ee222dc01
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/seq.hpp
@@ -0,0 +1,122 @@
+// 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)
+
+#ifndef TEST_SUPPORT_SEQ_HPP
+#define TEST_SUPPORT_SEQ_HPP
+
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/concept/sequence.hpp>
+#include <boost/hana/fwd/core/make.hpp>
+#include <boost/hana/fwd/drop_front.hpp>
+#include <boost/hana/fwd/fold_left.hpp>
+#include <boost/hana/fwd/is_empty.hpp>
+#include <boost/hana/fwd/length.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/unpack.hpp>
+
+
+struct Seq;
+
+template <typename Storage>
+struct seq_type {
+ explicit constexpr seq_type(Storage s) : storage(s) { }
+ Storage storage;
+ using hana_tag = Seq;
+};
+
+struct seq_t {
+ template <typename ...Xs>
+ constexpr auto operator()(Xs&& ...xs) const {
+ auto storage = boost::hana::make_tuple(xs...);
+ return seq_type<decltype(storage)>(storage);
+ }
+};
+constexpr seq_t seq{};
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //
+ // Define either one to select which MCD is used:
+ // BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
+ // BOOST_HANA_TEST_FOLDABLE_UNPACK_MCD
+ // BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD
+ //
+ // If neither is defined, the MCD used is unspecified.
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
+ template <>
+ struct fold_left_impl<Seq> {
+ template <typename Xs, typename S, typename F>
+ static constexpr auto apply(Xs xs, S s, F f) {
+ return hana::fold_left(xs.storage, s, f);
+ }
+
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs xs, F f) {
+ return hana::fold_left(xs.storage, f);
+ }
+ };
+#elif defined(BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD)
+ template <>
+ struct length_impl<Seq> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs) {
+ return hana::length(xs.storage);
+ }
+ };
+#else
+ template <>
+ struct unpack_impl<Seq> {
+ template <typename Xs, typename F>
+ static constexpr auto apply(Xs xs, F f)
+ { return hana::unpack(xs.storage, f); }
+ };
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<Seq> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N&& n) {
+ return hana::at(static_cast<Xs&&>(xs).storage, n);
+ }
+ };
+
+ template <>
+ struct drop_front_impl<Seq> {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs xs, N n) {
+ return hana::unpack(hana::drop_front(xs.storage, n), ::seq);
+ }
+ };
+
+ template <>
+ struct is_empty_impl<Seq> {
+ template <typename Xs>
+ static constexpr auto apply(Xs xs) {
+ return hana::is_empty(xs.storage);
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<Seq> {
+ static constexpr bool value = true;
+ };
+
+ template <>
+ struct make_impl<Seq> {
+ template <typename ...Xs>
+ static constexpr auto apply(Xs&& ...xs) {
+ return ::seq(static_cast<Xs&&>(xs)...);
+ }
+ };
+}} // end namespace boost::hana
+
+#endif // !TEST_SUPPORT_SEQ_HPP
diff --git a/src/boost/libs/hana/test/_include/support/tracked.hpp b/src/boost/libs/hana/test/_include/support/tracked.hpp
new file mode 100644
index 000000000..215ffba4d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/tracked.hpp
@@ -0,0 +1,120 @@
+// 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)
+
+#ifndef TEST_SUPPORT_TRACKED_HPP
+#define TEST_SUPPORT_TRACKED_HPP
+
+// Define this if you want Tracked objects to print information to stderr.
+// #define TRACKED_PRINT_STUFF
+
+#include <boost/hana/assert.hpp>
+
+#ifdef TRACKED_PRINT_STUFF
+# include <iostream>
+#endif
+
+#include <iosfwd>
+
+
+struct Tracked {
+ enum class State { CONSTRUCTED, MOVED_FROM, DESTROYED };
+
+ int value;
+ State state;
+
+ explicit Tracked(int k) : value{k}, state{State::CONSTRUCTED} {
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "constructing " << *this << '\n';
+#endif
+ }
+
+ Tracked(Tracked const& t) : value{t.value}, state{State::CONSTRUCTED} {
+ BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
+ "copying a moved-from object");
+
+ BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
+ "copying a destroyed object");
+
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "copying " << *this << '\n';
+#endif
+ }
+
+ Tracked(Tracked&& t) : value{t.value}, state{State::CONSTRUCTED} {
+ BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
+ "double moving from an object");
+
+ BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
+ "moving from a destroyed object");
+
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "moving " << t << '\n';
+#endif
+ t.state = State::MOVED_FROM;
+ }
+
+ Tracked& operator=(Tracked const& other) {
+ BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
+ "assigning to a destroyed object");
+
+ BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
+ "assigning a moved-from object");
+
+ BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
+ "assigning a destroyed object");
+
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "assigning " << other << " to " << *this << '\n';
+#endif
+ this->value = other.value;
+ return *this;
+ }
+
+ Tracked& operator=(Tracked&& other) {
+ BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
+ "assigning to a destroyed object");
+
+ BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
+ "double-moving from an object");
+
+ BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
+ "assigning a destroyed object");
+
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "assigning " << other << " to " << *this << '\n';
+#endif
+ this->value = other.value;
+ other.state = State::MOVED_FROM;
+ return *this;
+ }
+
+ ~Tracked() {
+ BOOST_HANA_RUNTIME_CHECK(state != State::DESTROYED &&
+ "double-destroying an object");
+
+#ifdef TRACKED_PRINT_STUFF
+ std::cerr << "destructing " << *this << '\n';
+#endif
+ state = State::DESTROYED;
+ }
+
+ template <typename CharT, typename Traits>
+ friend std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& os, Tracked const& t) {
+ os << "Tracked{" << t.value << "}";
+ switch (t.state) {
+ case State::CONSTRUCTED:
+ os << "[ok]"; break;
+ case State::MOVED_FROM:
+ os << "[moved from]"; break;
+ case State::DESTROYED:
+ os << "[destroyed]"; break;
+ default:
+ BOOST_HANA_RUNTIME_CHECK(false && "never reached");
+ }
+ return os;
+ }
+};
+
+#endif // !TEST_SUPPORT_TRACKED_HPP
diff --git a/src/boost/libs/hana/test/_include/support/tracked_move_only.hpp b/src/boost/libs/hana/test/_include/support/tracked_move_only.hpp
new file mode 100644
index 000000000..03e9d5da6
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/support/tracked_move_only.hpp
@@ -0,0 +1,45 @@
+// 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)
+
+#ifndef TEST_SUPPORT_TRACKED_MOVE_ONLY_HPP
+#define TEST_SUPPORT_TRACKED_MOVE_ONLY_HPP
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/fwd/hash.hpp>
+#include <boost/hana/type.hpp>
+
+#include <support/tracked.hpp>
+
+#include <utility>
+
+
+// A move-only type that's Tracked. It is also Comparable and Hashable so it
+// can be used in associative containers.
+template <int i>
+struct TrackedMoveOnly : Tracked {
+ TrackedMoveOnly() : Tracked(i) { }
+ TrackedMoveOnly(TrackedMoveOnly const&) = delete;
+ TrackedMoveOnly& operator=(TrackedMoveOnly const&) = delete;
+ TrackedMoveOnly(TrackedMoveOnly&& x)
+ : Tracked(std::move(x))
+ { }
+};
+
+template <int i, int j>
+constexpr auto operator==(TrackedMoveOnly<i> const&, TrackedMoveOnly<j> const&)
+{ return boost::hana::bool_c<i == j>; }
+
+template <int i, int j>
+constexpr auto operator!=(TrackedMoveOnly<i> const&, TrackedMoveOnly<j> const&)
+{ return boost::hana::bool_c<i != j>; }
+
+namespace boost { namespace hana {
+ template <int i>
+ struct hash_impl<TrackedMoveOnly<i>> {
+ static constexpr auto apply(TrackedMoveOnly<i> const&)
+ { return hana::type_c<TrackedMoveOnly<i>>; };
+ };
+}}
+
+#endif // !TEST_SUPPORT_TRACKED_MOVE_ONLY_HPP