summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/example/misc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/hana/example/misc
parentInitial commit. (diff)
downloadceph-upstream/16.2.11+ds.tar.xz
ceph-upstream/16.2.11+ds.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/hana/example/misc')
-rw-r--r--src/boost/libs/hana/example/misc/dimensional_analysis.cpp71
-rw-r--r--src/boost/libs/hana/example/misc/from_json.cpp129
-rw-r--r--src/boost/libs/hana/example/misc/indexed_sort.cpp62
-rw-r--r--src/boost/libs/hana/example/misc/infinite_list.cpp116
-rw-r--r--src/boost/libs/hana/example/misc/infinite_set.cpp321
-rw-r--r--src/boost/libs/hana/example/misc/lambda_tuple.cpp244
-rw-r--r--src/boost/libs/hana/example/misc/nth.cpp45
-rw-r--r--src/boost/libs/hana/example/misc/overload_linearly.cpp42
-rw-r--r--src/boost/libs/hana/example/misc/printf.cpp66
-rw-r--r--src/boost/libs/hana/example/misc/ref_tuple.cpp92
-rw-r--r--src/boost/libs/hana/example/misc/restricted_function.cpp143
-rw-r--r--src/boost/libs/hana/example/misc/tree.cpp144
12 files changed, 1475 insertions, 0 deletions
diff --git a/src/boost/libs/hana/example/misc/dimensional_analysis.cpp b/src/boost/libs/hana/example/misc/dimensional_analysis.cpp
new file mode 100644
index 000000000..40872df9f
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/dimensional_analysis.cpp
@@ -0,0 +1,71 @@
+// 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/equal.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/zip_with.hpp>
+
+#include <functional>
+namespace hana = boost::hana;
+
+
+//
+// Example of implementing basic dimensional analysis using Hana
+//
+
+
+// base dimensions M L T I K J N
+using mass = decltype(hana::tuple_c<int, 1, 0, 0, 0, 0, 0, 0>);
+using length = decltype(hana::tuple_c<int, 0, 1, 0, 0, 0, 0, 0>);
+using time_ = decltype(hana::tuple_c<int, 0, 0, 1, 0, 0, 0, 0>);
+using charge = decltype(hana::tuple_c<int, 0, 0, 0, 1, 0, 0, 0>);
+using temperature = decltype(hana::tuple_c<int, 0, 0, 0, 0, 1, 0, 0>);
+using intensity = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 1, 0>);
+using amount = decltype(hana::tuple_c<int, 0, 0, 0, 0, 0, 0, 1>);
+
+// composite dimensions
+using velocity = decltype(hana::tuple_c<int, 0, 1, -1, 0, 0, 0, 0>); // M/T
+using acceleration = decltype(hana::tuple_c<int, 0, 1, -2, 0, 0, 0, 0>); // M/T^2
+using force = decltype(hana::tuple_c<int, 1, 1, -2, 0, 0, 0, 0>); // ML/T^2
+
+
+template <typename Dimensions>
+struct quantity {
+ double value_;
+
+ explicit quantity(double v) : value_(v) { }
+
+ template <typename OtherDimensions>
+ explicit quantity(quantity<OtherDimensions> other)
+ : value_(other.value_)
+ {
+ static_assert(Dimensions{} == OtherDimensions{},
+ "Constructing quantities with incompatible dimensions!");
+ }
+
+ explicit operator double() const { return value_; }
+};
+
+template <typename D1, typename D2>
+auto operator*(quantity<D1> a, quantity<D2> b) {
+ using D = decltype(hana::zip_with(std::plus<>{}, D1{}, D2{}));
+ return quantity<D>{static_cast<double>(a) * static_cast<double>(b)};
+}
+
+template <typename D1, typename D2>
+auto operator/(quantity<D1> a, quantity<D2> b) {
+ using D = decltype(hana::zip_with(std::minus<>{}, D1{}, D2{}));
+ return quantity<D>{static_cast<double>(a) / static_cast<double>(b)};
+}
+
+int main() {
+ quantity<mass> m{10.3};
+ quantity<length> d{3.6};
+ quantity<time_> t{2.4};
+ quantity<velocity> v{d / t};
+ quantity<acceleration> a{3.9};
+ quantity<force> f{m * a};
+}
diff --git a/src/boost/libs/hana/example/misc/from_json.cpp b/src/boost/libs/hana/example/misc/from_json.cpp
new file mode 100644
index 000000000..a28cac1e5
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/from_json.cpp
@@ -0,0 +1,129 @@
+// 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/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/concept/struct.hpp>
+#include <boost/hana/define_struct.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/keys.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <type_traits>
+namespace hana = boost::hana;
+
+
+struct Car {
+ BOOST_HANA_DEFINE_STRUCT(Car,
+ (std::string, brand),
+ (std::string, model)
+ );
+};
+
+struct Person {
+ BOOST_HANA_DEFINE_STRUCT(Person,
+ (std::string, name),
+ (std::string, last_name),
+ (int, age)
+ );
+};
+
+template <typename T>
+ std::enable_if_t<std::is_same<T, int>::value,
+T> from_json(std::istream& in) {
+ T result;
+ in >> result;
+ return result;
+}
+
+template <typename T>
+ std::enable_if_t<std::is_same<T, std::string>::value,
+T> from_json(std::istream& in) {
+ char quote;
+ in >> quote;
+
+ T result;
+ char c;
+ while (in.get(c) && c != '"') {
+ result += c;
+ }
+ return result;
+}
+
+
+template <typename T>
+ std::enable_if_t<hana::Struct<T>::value,
+T> from_json(std::istream& in) {
+ T result;
+ char brace;
+ in >> brace;
+
+ // CAREFUL: This only works if the input JSON contains the fields in the
+ // same order as the struct declares them.
+ hana::for_each(hana::keys(result), [&](auto key) {
+ in.ignore(std::numeric_limits<std::streamsize>::max(), ':');
+ auto& member = hana::at_key(result, key);
+ using Member = std::remove_reference_t<decltype(member)>;
+ member = from_json<Member>(in);
+ });
+ in >> brace;
+ return result;
+}
+
+template <typename Xs>
+ std::enable_if_t<hana::Sequence<Xs>::value,
+Xs> from_json(std::istream& in) {
+ Xs result;
+ char bracket;
+ in >> bracket;
+ hana::length(result).times.with_index([&](auto i) {
+ if (i != 0u) {
+ char comma;
+ in >> comma;
+ }
+
+ auto& element = hana::at(result, i);
+ using Element = std::remove_reference_t<decltype(element)>;
+ element = from_json<Element>(in);
+ });
+ in >> bracket;
+ return result;
+}
+
+
+int main() {
+ std::istringstream json(R"EOS(
+ [
+ {
+ "name": "John",
+ "last_name": "Doe",
+ "age": 30
+ },
+ {
+ "brand": "BMW",
+ "model": "Z3"
+ },
+ {
+ "brand": "Audi",
+ "model": "A4"
+ }
+ ]
+ )EOS");
+
+ auto actual = from_json<hana::tuple<Person, Car, Car>>(json);
+
+ auto expected = hana::make_tuple(Person{"John", "Doe", 30},
+ Car{"BMW", "Z3"},
+ Car{"Audi", "A4"});
+
+ BOOST_HANA_RUNTIME_CHECK(actual == expected);
+}
diff --git a/src/boost/libs/hana/example/misc/indexed_sort.cpp b/src/boost/libs/hana/example/misc/indexed_sort.cpp
new file mode 100644
index 000000000..de8308e4d
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/indexed_sort.cpp
@@ -0,0 +1,62 @@
+// 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/at.hpp>
+#include <boost/hana/back.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/less.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/sort.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/zip.hpp>
+
+#include <type_traits>
+namespace hana = boost::hana;
+using namespace hana::literals;
+
+
+auto indexed_sort = [](auto list, auto predicate) {
+ auto indexed_list = hana::zip(
+ list,
+ hana::to_tuple(hana::make_range(0_c, hana::length(list)))
+ );
+ auto sorted = hana::sort.by(predicate ^hana::on^ hana::front, indexed_list);
+ return hana::make_pair(hana::transform(sorted, hana::front),
+ hana::transform(sorted, hana::back));
+};
+
+int main() {
+ auto types = hana::tuple_t<char[4], char[2], char[1], char[5], char[3]>;
+ auto sorted = indexed_sort(types, [](auto t, auto u) {
+ return hana::sizeof_(t) < hana::sizeof_(u);
+ });
+ using Tup = decltype(
+ hana::unpack(hana::first(sorted), hana::template_<hana::tuple>)
+ )::type;
+ auto indices = hana::second(indexed_sort(hana::second(sorted), hana::less));
+
+ // When accessed through the indices sequence, the tuple appears to be
+ // ordered as the `types` above. However, as can be seen in the
+ // static_assert below, the tuple is actually ordered differently.
+ Tup tup;
+ char const(&a)[4] = tup[indices[0_c]];
+ char const(&b)[2] = tup[indices[1_c]];
+ char const(&c)[1] = tup[indices[2_c]];
+ char const(&d)[5] = tup[indices[3_c]];
+ char const(&e)[3] = tup[indices[4_c]];
+
+ static_assert(std::is_same<
+ Tup,
+ hana::tuple<char[1], char[2], char[3], char[4], char[5]>
+ >{}, "");
+
+ (void)a; (void)b; (void)c; (void)d; (void)e;
+}
diff --git a/src/boost/libs/hana/example/misc/infinite_list.cpp b/src/boost/libs/hana/example/misc/infinite_list.cpp
new file mode 100644
index 000000000..b5eecaf18
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/infinite_list.cpp
@@ -0,0 +1,116 @@
+// 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/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/eval.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/fix.hpp>
+#include <boost/hana/functional/iterate.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/empty.hpp>
+#include <boost/hana/fwd/prepend.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/value.hpp>
+
+#include <cstddef>
+namespace hana = boost::hana;
+
+
+// A naive implementation of a lazy compile-time list, i.e. a tuple that can
+// potentially have an infinite number of elements (but that infinity must be
+// determinable at compile-time).
+
+struct LazyList;
+
+template <typename X, typename Xs>
+struct lazy_cons_type {
+ X x;
+ Xs xs;
+ using hana_tag = LazyList;
+};
+
+auto lazy_cons = [](auto x, auto xs) {
+ return lazy_cons_type<decltype(x), decltype(xs)>{x, xs};
+};
+
+struct lazy_nil_type { using hana_tag = LazyList; };
+
+constexpr lazy_nil_type lazy_nil{};
+
+auto repeat = hana::fix([](auto repeat, auto x) {
+ return lazy_cons(x, hana::make_lazy(repeat)(x));
+});
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct at_impl<LazyList> {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& lcons, N const& n) {
+ return hana::drop_front(lcons, n).x;
+ }
+ };
+
+ namespace detail {
+ struct eval_tail {
+ template <typename Xs>
+ constexpr auto operator()(Xs const& lcons) const {
+ return hana::eval(lcons.xs);
+ }
+
+ constexpr auto operator()(lazy_nil_type const&) const {
+ return lazy_nil;
+ }
+ };
+ }
+
+ template <>
+ struct drop_front_impl<LazyList> {
+ template <typename Xs, typename N>
+ static constexpr auto apply(Xs&& lcons, N const&) {
+ return hana::iterate<N::value>(detail::eval_tail{}, lcons);
+ }
+ };
+
+ template <>
+ struct is_empty_impl<LazyList> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const&)
+ { return hana::false_c; }
+
+ static constexpr auto apply(lazy_nil_type const&)
+ { return hana::true_c; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct prepend_impl<LazyList> {
+ template <typename Xs, typename X>
+ static constexpr auto apply(Xs xs, X x)
+ { return lazy_cons(x, hana::make_lazy(xs)); }
+ };
+
+ template <>
+ struct empty_impl<LazyList> {
+ static constexpr auto apply()
+ { return lazy_nil; }
+ };
+}}
+
+
+int main() {
+ BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(repeat(1)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::front(repeat(1)) == 1);
+ BOOST_HANA_CONSTEXPR_CHECK(hana::at(repeat(1), hana::size_c<10>) == 1);
+}
diff --git a/src/boost/libs/hana/example/misc/infinite_set.cpp b/src/boost/libs/hana/example/misc/infinite_set.cpp
new file mode 100644
index 000000000..6bccfd535
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/infinite_set.cpp
@@ -0,0 +1,321 @@
+// 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/and.hpp>
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/ap.hpp>
+#include <boost/hana/fwd/equal.hpp>
+#include <boost/hana/fwd/find_if.hpp>
+#include <boost/hana/fwd/lift.hpp>
+#include <boost/hana/fwd/union.hpp>
+#include <boost/hana/if.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/transform.hpp>
+namespace hana = boost::hana;
+
+
+// A `Monad` for searching infinite sets in finite time.
+//
+// Taken from http://goo.gl/XJeDy8.
+struct infinite_set_tag { };
+
+template <typename Find>
+struct infinite_set {
+ Find find;
+ using hana_tag = infinite_set_tag;
+};
+
+template <typename Pred>
+constexpr infinite_set<Pred> make_infinite_set(Pred pred) {
+ return {pred};
+}
+
+template <typename X>
+constexpr auto singleton(X x) {
+ return make_infinite_set([=](auto /*p*/) { return x; });
+}
+
+template <typename X, typename Y>
+constexpr auto doubleton(X x, Y y) {
+ return make_infinite_set([=](auto p) {
+ return hana::if_(p(x), x, y);
+ });
+}
+
+namespace boost { namespace hana {
+ template <>
+ struct union_impl<infinite_set_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs xs, Ys ys) {
+ return flatten(doubleton(xs, ys));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<infinite_set_tag, infinite_set_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr auto apply(Xs xs, Ys ys)
+ { return and_(is_subset(xs, ys), is_subset(ys, xs)); }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<infinite_set_tag> {
+ template <typename Set, typename F>
+ static constexpr auto apply(Set set, F f) {
+ return make_infinite_set([=](auto q) {
+ return f(set.find(compose(q, f)));
+ });
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<infinite_set_tag> {
+ template <typename X>
+ static constexpr auto apply(X x)
+ { return singleton(x); }
+ };
+
+ template <>
+ struct ap_impl<infinite_set_tag> {
+ template <typename F, typename Set>
+ static constexpr auto apply(F fset, Set set) {
+ return flatten(transform(fset, partial(transform, set)));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct flatten_impl<infinite_set_tag> {
+ template <typename Set>
+ static constexpr auto apply(Set set) {
+ return make_infinite_set([=](auto p) {
+ return set.find([=](auto set) {
+ return any_of(set, p);
+ }).find(p);
+ });
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct find_if_impl<infinite_set_tag> {
+ template <typename Set, typename Pred>
+ static constexpr auto apply(Set set, Pred p) {
+ auto x = set.find(p);
+ return if_(p(x), hana::just(x), hana::nothing);
+ }
+ };
+
+ template <>
+ struct any_of_impl<infinite_set_tag> {
+ template <typename Set, typename Pred>
+ static constexpr auto apply(Set set, Pred p) {
+ return p(set.find(p));
+ }
+ };
+}} // end namespace boost::hana
+
+//////////////////////////////////////////////////////////////////////////////
+// Tests
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/ap.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/union.hpp>
+namespace hana = boost::hana;
+
+
+template <int i>
+constexpr int n = i;
+
+template <int i>
+constexpr auto c = hana::int_c<i>;
+
+int main() {
+ auto f = [](auto n) { return n + hana::int_c<10>; };
+ auto g = [](auto n) { return n + hana::int_c<100>; };
+
+ // union_
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::union_(singleton(c<0>), singleton(c<0>)),
+ singleton(c<0>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::union_(singleton(c<0>), singleton(c<1>)),
+ doubleton(c<0>, c<1>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::union_(singleton(c<0>), doubleton(c<0>, c<1>)),
+ doubleton(c<0>, c<1>)
+ ));
+ }
+
+ // Comparable
+ {
+ // equal
+ {
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(singleton(n<0>), singleton(n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), singleton(n<1>))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(singleton(n<0>), doubleton(n<0>, n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), doubleton(n<0>, n<1>))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), doubleton(n<1>, n<1>))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(doubleton(n<0>, n<1>), doubleton(n<0>, n<1>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(doubleton(n<0>, n<1>), doubleton(n<1>, n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(doubleton(n<0>, n<1>), doubleton(n<0>, n<0>))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(doubleton(n<0>, n<1>), doubleton(n<3>, n<4>))));
+ }
+ }
+
+ // Functor
+ {
+ // transform
+ {
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
+ hana::transform(singleton(n<0>), f),
+ singleton(f(n<0>))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
+ hana::transform(doubleton(n<0>, n<1>), f),
+ doubleton(f(n<0>), f(n<1>))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
+ hana::transform(doubleton(n<0>, n<0>), f),
+ singleton(f(n<0>))
+ ));
+ }
+ }
+
+ // Applicative
+ {
+ // ap
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(singleton(f), singleton(c<0>)),
+ singleton(f(c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(singleton(f), doubleton(c<0>, c<1>)),
+ doubleton(f(c<0>), f(c<1>))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(doubleton(f, g), singleton(c<0>)),
+ doubleton(f(c<0>), g(c<0>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(doubleton(f, g), doubleton(c<0>, c<1>)),
+ hana::union_(doubleton(f(c<0>), f(c<1>)),
+ doubleton(g(c<0>), g(c<1>)))
+ ));
+ }
+
+ // lift
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::lift<infinite_set_tag>(c<0>),
+ singleton(c<0>)
+ ));
+ }
+ }
+
+ // Monad
+ {
+ // flatten
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(singleton(singleton(c<0>))),
+ singleton(c<0>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(singleton(doubleton(c<0>, c<1>))),
+ doubleton(c<0>, c<1>)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(doubleton(singleton(c<0>), singleton(c<1>))),
+ doubleton(c<0>, c<1>)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(doubleton(doubleton(c<0>, c<1>), singleton(c<2>))),
+ hana::union_(doubleton(c<0>, c<1>), singleton(c<2>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(doubleton(singleton(c<0>), doubleton(c<1>, c<2>))),
+ hana::union_(doubleton(c<0>, c<1>), singleton(c<2>))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(doubleton(doubleton(c<0>, c<1>), doubleton(c<2>, c<3>))),
+ hana::union_(doubleton(c<0>, c<1>), doubleton(c<2>, c<3>))
+ ));
+ }
+ }
+
+ // Searchable
+ {
+ // any_of
+ {
+ BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(singleton(n<0>), hana::equal.to(n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any_of(singleton(n<0>), hana::equal.to(n<1>))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<1>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<2>))));
+ }
+
+ // find_if
+ {
+ BOOST_HANA_CONSTANT_CHECK(hana::find_if(singleton(c<0>), hana::equal.to(c<0>)) == hana::just(c<0>));
+ BOOST_HANA_CONSTANT_CHECK(hana::find_if(singleton(c<1>), hana::equal.to(c<0>)) == hana::nothing);
+
+ BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<0>)) == hana::just(c<0>));
+ BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<1>)) == hana::just(c<1>));
+ BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<2>)) == hana::nothing);
+ }
+
+ // is_subset
+ {
+ BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<0>), singleton(n<0>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(singleton(n<1>), singleton(n<0>))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<0>), doubleton(n<0>, n<1>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<1>), doubleton(n<0>, n<1>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(singleton(n<2>), doubleton(n<0>, n<1>))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(doubleton(n<0>, n<1>), doubleton(n<0>, n<1>)));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(doubleton(n<0>, n<2>), doubleton(n<0>, n<1>))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(doubleton(n<2>, n<3>), doubleton(n<0>, n<1>))));
+ }
+ }
+}
diff --git a/src/boost/libs/hana/example/misc/lambda_tuple.cpp b/src/boost/libs/hana/example/misc/lambda_tuple.cpp
new file mode 100644
index 000000000..d3bcbd191
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/lambda_tuple.cpp
@@ -0,0 +1,244 @@
+// 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/at.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/detail/variadic/at.hpp>
+#include <boost/hana/detail/variadic/drop_into.hpp>
+#include <boost/hana/detail/variadic/take.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/on.hpp>
+#include <boost/hana/fwd/append.hpp>
+#include <boost/hana/fwd/at.hpp>
+#include <boost/hana/fwd/concat.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/empty.hpp>
+#include <boost/hana/fwd/front.hpp>
+#include <boost/hana/fwd/prepend.hpp>
+#include <boost/hana/fwd/take_front.hpp>
+#include <boost/hana/fwd/transform.hpp>
+#include <boost/hana/fwd/unpack.hpp>
+#include <boost/hana/fwd/zip_shortest_with.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/min.hpp>
+#include <boost/hana/minimum.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <utility>
+namespace hana = boost::hana;
+
+
+// An interesting way of implementing tuple using lambda captures.
+
+struct lambda_tuple_tag { };
+
+template <typename Storage>
+struct lambda_tuple_t {
+ explicit constexpr lambda_tuple_t(Storage&& s)
+ : storage(std::move(s))
+ { }
+
+ using hana_tag = lambda_tuple_tag;
+ Storage storage;
+};
+
+auto lambda_tuple = [](auto ...xs) {
+ auto storage = [=](auto f) -> decltype(auto) { return f(xs...); };
+ return lambda_tuple_t<decltype(storage)>{std::move(storage)};
+};
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct unpack_impl<lambda_tuple_tag> {
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
+ return static_cast<Xs&&>(xs).storage(static_cast<F&&>(f));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<lambda_tuple_tag> {
+ template <typename Xs, typename F>
+ static constexpr decltype(auto) apply(Xs&& xs, F f) {
+ return static_cast<Xs&&>(xs).storage(
+ [f(std::move(f))](auto&& ...xs) -> decltype(auto) {
+ return lambda_tuple(f(static_cast<decltype(xs)&&>(xs))...);
+ }
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct front_impl<lambda_tuple_tag> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return static_cast<Xs&&>(xs).storage(
+ [](auto&& x, auto&& ...) -> decltype(auto) {
+ return id(static_cast<decltype(x)&&>(x));
+ }
+ );
+ }
+ };
+
+ template <>
+ struct is_empty_impl<lambda_tuple_tag> {
+ template <typename Xs>
+ static constexpr decltype(auto) apply(Xs&& xs) {
+ return static_cast<Xs&&>(xs).storage(
+ [](auto const& ...xs) -> decltype(auto) {
+ return hana::bool_c<sizeof...(xs) == 0>;
+ }
+ );
+ }
+ };
+
+ template <>
+ struct at_impl<lambda_tuple_tag> {
+ template <typename Xs, typename Index>
+ static constexpr decltype(auto) apply(Xs&& xs, Index const&) {
+ return static_cast<Xs&&>(xs).storage(
+ detail::variadic::at<Index::value>
+ );
+ }
+ };
+
+ template <>
+ struct drop_front_impl<lambda_tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
+ auto m = min(n, length(xs));
+ return static_cast<Xs&&>(xs).storage(
+ detail::variadic::drop_into<hana::value(m)>(lambda_tuple)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct concat_impl<lambda_tuple_tag> {
+ template <typename Xs, typename Ys>
+ static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) {
+ return static_cast<Xs&&>(xs).storage(
+ [ys(static_cast<Ys&&>(ys))](auto&& ...xs) -> decltype(auto) {
+ return std::move(ys).storage(
+ // We can't initialize the capture with perfect
+ // forwarding since that's not supported by the
+ // language.
+ [=](auto&& ...ys) -> decltype(auto) {
+ return lambda_tuple(
+ std::move(xs)...,
+ static_cast<decltype(ys)&&>(ys)...
+ );
+ }
+ );
+ }
+ );
+ }
+ };
+
+ template <>
+ struct prepend_impl<lambda_tuple_tag> {
+ template <typename Xs, typename X>
+ static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
+ return static_cast<Xs&&>(xs).storage(
+ [x(static_cast<X&&>(x))](auto&& ...xs) -> decltype(auto) {
+ return lambda_tuple(
+ std::move(x),
+ static_cast<decltype(xs)&&>(xs)...
+ );
+ }
+ );
+ }
+ };
+
+ template <>
+ struct append_impl<lambda_tuple_tag> {
+ template <typename Xs, typename X>
+ static constexpr decltype(auto) apply(Xs&& xs, X&& x) {
+ return static_cast<Xs&&>(xs).storage(
+ [x(static_cast<X&&>(x))](auto&& ...xs) -> decltype(auto) {
+ return lambda_tuple(
+ static_cast<decltype(xs)&&>(xs)...,
+ std::move(x)
+ );
+ }
+ );
+ }
+ };
+
+ template <>
+ struct empty_impl<lambda_tuple_tag> {
+ static BOOST_HANA_CONSTEXPR_LAMBDA decltype(auto) apply() {
+ return lambda_tuple();
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct Sequence<lambda_tuple_tag> {
+ static constexpr bool value = true;
+ };
+
+ template <>
+ struct take_front_impl<lambda_tuple_tag> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
+ auto m = min(n, length(xs));
+ return static_cast<Xs&&>(xs).storage(
+ detail::variadic::take<decltype(m)::value>
+ )(lambda_tuple);
+ }
+ };
+
+ template <>
+ struct zip_shortest_with_impl<lambda_tuple_tag> {
+ template <typename F, typename ...Xss>
+ static constexpr auto apply(F f, Xss ...tuples) {
+ auto go = [=](auto index, auto ...nothing) {
+ return always(f)(nothing...)(at(tuples, index)...);
+ };
+ auto zip_length = minimum(lambda_tuple(length(tuples)...));
+ return unpack(make_range(size_c<0>, zip_length),
+ on(lambda_tuple, go)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // make
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct make_impl<lambda_tuple_tag> {
+ template <typename ...Xs>
+ static constexpr decltype(auto) apply(Xs&& ...xs) {
+ return lambda_tuple(static_cast<Xs&&>(xs)...);
+ }
+ };
+}} // end namespace boost::hana
+
+
+int main() {
+ auto xs = lambda_tuple(1, '2', 3.3);
+ static_assert(!decltype(hana::is_empty(xs))::value, "");
+}
diff --git a/src/boost/libs/hana/example/misc/nth.cpp b/src/boost/libs/hana/example/misc/nth.cpp
new file mode 100644
index 000000000..ffbdf1eb8
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/nth.cpp
@@ -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)
+
+#include <boost/hana/functional/arg.hpp>
+
+#include <cstddef>
+#include <utility>
+namespace hana = boost::hana;
+
+
+constexpr int to_int(char c)
+{ return static_cast<int>(c) - 48; }
+
+template <std::size_t N>
+constexpr long long parse(const char (&arr)[N]) {
+ long long number = 0, base = 1;
+ for (std::size_t i = 0; i < N; ++i) {
+ number += to_int(arr[N - 1 - i]) * base;
+ base *= 10;
+ }
+ return number;
+}
+
+template <char ...c>
+struct pick {
+ static constexpr unsigned long n = parse<sizeof...(c)>({c...});
+
+ template <typename ...T>
+ constexpr auto operator()(T&& ...args) const
+ { return hana::arg<n>(std::forward<T>(args)...); }
+};
+
+template <char ...c> constexpr pick<c...> operator"" _st() { return {}; }
+template <char ...c> constexpr pick<c...> operator"" _nd() { return {}; }
+template <char ...c> constexpr pick<c...> operator"" _rd() { return {}; }
+template <char ...c> constexpr pick<c...> operator"" _th() { return {}; }
+
+
+static_assert(1_st(1, '2', 3.3, 444) == 1, "");
+static_assert(2_nd(1, '2', 3.3, 444) == '2', "");
+static_assert(3_rd(1, '2', 3.3, 444) == 3.3, "");
+static_assert(4_th(1, '2', 3.3, 444) == 444, "");
+
+int main() { }
diff --git a/src/boost/libs/hana/example/misc/overload_linearly.cpp b/src/boost/libs/hana/example/misc/overload_linearly.cpp
new file mode 100644
index 000000000..a41174a27
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/overload_linearly.cpp
@@ -0,0 +1,42 @@
+// 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/assert.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/type.hpp>
+
+#include <string>
+namespace hana = boost::hana;
+
+
+// We have an utility in the Functional module that does pretty much the
+// same, but is more compile-time efficient. It is still interesting to
+// see this implemented with sequences and the SFINAE combinator.
+
+auto overload_linearly = [](auto ...candidates) {
+ return [=](auto ...args) {
+ auto maybe_function = hana::find_if(hana::make_tuple(candidates...), [=](auto f) {
+ return hana::is_valid(f)(args...);
+ });
+ auto result = hana::transform(maybe_function, [=](auto f) {
+ return f(args...);
+ });
+ return result;
+ };
+};
+
+int main() {
+ auto f = ::overload_linearly(
+ [](std::string s) { return s + "abcd"; },
+ [](int i) { return i + 1; },
+ [](double f) { return f + 2; }
+ );
+
+ BOOST_HANA_RUNTIME_CHECK(f(1) == hana::just(1 + 1));
+ BOOST_HANA_RUNTIME_CHECK(f(2.3) == hana::just(static_cast<int>(2.3) + 1));
+}
diff --git a/src/boost/libs/hana/example/misc/printf.cpp b/src/boost/libs/hana/example/misc/printf.cpp
new file mode 100644
index 000000000..01f5a9abf
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/printf.cpp
@@ -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)
+
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/core/is_a.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/map.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/prepend.hpp>
+#include <boost/hana/string.hpp>
+#include <boost/hana/sum.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/type.hpp>
+#include <boost/hana/unpack.hpp>
+
+#include <cstdio>
+namespace hana = boost::hana;
+
+
+constexpr auto formats = hana::make_map(
+ hana::make_pair(hana::type_c<int>, hana::string_c<'%', 'd'>),
+ hana::make_pair(hana::type_c<float>, hana::string_c<'%', 'f'>),
+ hana::make_pair(hana::type_c<char const*>, hana::string_c<'%', 's'>)
+);
+
+template <typename ...Tokens>
+constexpr auto format(Tokens ...tokens_) {
+ auto tokens = hana::make_tuple(tokens_...);
+
+ // If you don't care about constexpr-ness of `format`, you can use
+ // this lambda instead of `compose(partial(...), typeid_)`:
+ //
+ // [](auto token) {
+ // return formats[typeid_(token)];
+ // }
+ auto format_string_tokens = hana::adjust_if(tokens,
+ hana::compose(hana::not_, hana::is_a<hana::string_tag>),
+ hana::compose(hana::partial(hana::at_key, formats), hana::typeid_)
+ );
+
+ auto format_string = hana::sum<hana::string_tag>(format_string_tokens);
+ auto variables = hana::filter(tokens, hana::compose(hana::not_, hana::is_a<hana::string_tag>));
+ return hana::prepend(variables, format_string);
+}
+
+int main() {
+ int a = 1;
+ float b = 1.3;
+ char const* c = "abcdef";
+
+ auto args = format(
+ BOOST_HANA_STRING("first="), a
+ , BOOST_HANA_STRING(" second="), b
+ , BOOST_HANA_STRING(" third="), c
+ );
+
+ hana::unpack(args, [](auto fmt, auto ...args) {
+ std::printf(hana::to<char const*>(fmt), args...);
+ });
+}
diff --git a/src/boost/libs/hana/example/misc/ref_tuple.cpp b/src/boost/libs/hana/example/misc/ref_tuple.cpp
new file mode 100644
index 000000000..488925800
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/ref_tuple.cpp
@@ -0,0 +1,92 @@
+// 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/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <cstddef>
+#include <functional>
+namespace hana = boost::hana;
+
+
+// A tuple that holds reference_wrappers to its elements, instead of the
+// elements themselves.
+
+struct RefTuple { };
+
+template <typename ...T>
+struct ref_tuple;
+
+template <typename ...T>
+struct ref_tuple<T&...> {
+ hana::tuple<std::reference_wrapper<T>...> storage_;
+};
+
+
+namespace boost { namespace hana {
+ template <typename ...T>
+ struct tag_of<ref_tuple<T...>> {
+ using type = RefTuple;
+ };
+
+ template <>
+ struct make_impl<RefTuple> {
+ template <typename ...T>
+ static constexpr auto apply(T& ...t) {
+ return ref_tuple<T&...>{{std::ref(t)...}};
+ }
+ };
+
+ template <>
+ struct at_impl<RefTuple> {
+ template <typename Xs, typename N>
+ static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
+ return hana::at(static_cast<Xs&&>(xs).storage_, n).get();
+ }
+ };
+
+ template <>
+ struct is_empty_impl<RefTuple> {
+ template <typename Xs>
+ static constexpr auto apply(Xs const& xs) {
+ return hana::is_empty(xs.storage_);
+ }
+ };
+
+ template <>
+ struct drop_front_impl<RefTuple> {
+ template <std::size_t n, typename T, typename ...U, std::size_t ...i>
+ static constexpr auto helper(ref_tuple<T, U...> xs, std::index_sequence<i...>) {
+ return hana::make<RefTuple>(hana::at_c<n + i>(xs.storage_).get()...);
+ }
+
+ template <typename ...T, typename N>
+ static constexpr auto apply(ref_tuple<T...> xs, N const&) {
+ return helper<N::value>(xs, std::make_index_sequence<(
+ N::value < sizeof...(T) ? sizeof...(T) - N::value : 0
+ )>{});
+ }
+ };
+}} // end namespace boost::hana
+
+
+int main() {
+ int i = 0, j = 1, k = 2;
+
+ ref_tuple<int&, int&, int&> refs = hana::make<RefTuple>(i, j, k);
+ hana::at_c<0>(refs) = 3;
+ BOOST_HANA_RUNTIME_CHECK(i == 3);
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(refs)));
+
+ ref_tuple<int&, int&> tail = hana::drop_front(refs);
+ hana::at_c<0>(tail) = 4;
+ BOOST_HANA_RUNTIME_CHECK(j == 4);
+}
diff --git a/src/boost/libs/hana/example/misc/restricted_function.cpp b/src/boost/libs/hana/example/misc/restricted_function.cpp
new file mode 100644
index 000000000..6a290489b
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/restricted_function.cpp
@@ -0,0 +1,143 @@
+// 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/all_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/cartesian_product.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/demux.hpp>
+#include <boost/hana/fuse.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/mod.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/set.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+namespace hana = boost::hana;
+using namespace hana::literals;
+
+
+// A function that can have an arbitrary compile-time set of values as a domain
+// and co-domain. This is most likely purely of theoretical interest, but it
+// allows creating functions with very complex domains and co-domains that are
+// computed at compile-time.
+
+struct Function { };
+
+template <typename Domain, typename Codomain, typename F>
+struct function_type {
+ using hana_tag = Function;
+
+ Domain domain_;
+ Codomain codomain_;
+ F f_;
+
+ template <typename X>
+ constexpr auto operator()(X x) const {
+ BOOST_HANA_CONSTANT_ASSERT(boost::hana::contains(domain_, x));
+ return f_(x);
+ }
+};
+
+template <typename ...F, typename ...G>
+constexpr auto operator==(function_type<F...> f, function_type<G...> g)
+{ return hana::equal(f, g); }
+
+template <typename ...F, typename ...G>
+constexpr auto operator!=(function_type<F...> f, function_type<G...> g)
+{ return hana::not_equal(f, g); }
+
+
+auto function = [](auto domain, auto codomain) {
+ return [=](auto definition) {
+ return function_type<decltype(domain), decltype(codomain), decltype(definition)>{
+ domain, codomain, definition
+ };
+ };
+};
+
+template <typename Function>
+constexpr auto domain(Function f)
+{ return f.domain_; }
+
+template <typename Function>
+constexpr auto codomain(Function f)
+{ return f.codomain_; }
+
+template <typename Function>
+constexpr auto range(Function f) {
+ // We must convert to hana::tuple first because hana::set is not a Functor
+ return hana::to_set(hana::transform(hana::to_tuple(domain(f)), f));
+}
+
+template <typename P, typename Q>
+constexpr auto implies(P p, Q q) {
+ return hana::or_(hana::not_(p), q);
+}
+
+template <typename F>
+constexpr auto is_injective(F f) {
+ auto dom = hana::to_tuple(domain(f));
+ auto pairs = hana::cartesian_product(hana::make_tuple(dom, dom));
+ return hana::all_of(pairs, hana::fuse([&](auto x, auto y) {
+ return implies(hana::not_equal(x, y), hana::not_equal(f(x), f(y)));
+ }));
+}
+
+template <typename F>
+constexpr auto is_onto(F f) {
+ return codomain(f) == range(f);
+}
+
+namespace boost { namespace hana {
+ template <>
+ struct equal_impl<Function, Function> {
+ template <typename F, typename G>
+ static constexpr auto apply(F f, G g) {
+ return domain(f) == domain(g) &&
+ hana::all_of(domain(f), hana::demux(hana::equal)(f, g));
+ }
+ };
+}} // end namespace boost::hana
+
+int main() {
+ auto f = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(1_c, 2_c, 3_c, 4_c, 5_c, 6_c))(
+ [](auto x) { return x + 1_c; }
+ );
+
+ auto g = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(2_c, 3_c, 4_c))(
+ [](auto x) { return x + 1_c; }
+ );
+
+ auto h = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(0_c, 1_c, 2_c))(
+ [](auto x) { return x - 1_c; }
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(f == g);
+ BOOST_HANA_CONSTANT_CHECK(f != h);
+ BOOST_HANA_CONSTANT_CHECK(f(1_c) == 2_c);
+
+ BOOST_HANA_CONSTANT_CHECK(range(f) == hana::make_set(4_c, 3_c, 2_c));
+ BOOST_HANA_CONSTANT_CHECK(range(g) == hana::make_set(2_c, 3_c, 4_c));
+ BOOST_HANA_CONSTANT_CHECK(range(h) == hana::make_set(0_c, 1_c, 2_c));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(is_onto(f)));
+ BOOST_HANA_CONSTANT_CHECK(is_onto(g));
+ BOOST_HANA_CONSTANT_CHECK(is_onto(h));
+
+ auto even = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(hana::true_c, hana::false_c))(
+ [](auto x) { return x % 2_c == 0_c; }
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(is_injective(f));
+ BOOST_HANA_CONSTANT_CHECK(is_injective(g));
+ BOOST_HANA_CONSTANT_CHECK(is_injective(h));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(is_injective(even)));
+}
diff --git a/src/boost/libs/hana/example/misc/tree.cpp b/src/boost/libs/hana/example/misc/tree.cpp
new file mode 100644
index 000000000..c74a3e2c0
--- /dev/null
+++ b/src/boost/libs/hana/example/misc/tree.cpp
@@ -0,0 +1,144 @@
+// 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/and.hpp>
+#include <boost/hana/ap.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/sum.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+namespace hana = boost::hana;
+
+
+struct tree_tag;
+
+template <typename X, typename Subforest>
+struct node {
+ X value;
+ Subforest subforest;
+
+ using hana_tag = tree_tag;
+};
+
+constexpr auto make_forest = hana::make_tuple;
+
+template <typename X, typename Subforest>
+constexpr auto make_node(X x, Subforest subforest) {
+ return node<X, Subforest>{x, subforest};
+}
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct equal_impl<tree_tag, tree_tag> {
+ template <typename Node1, typename Node2>
+ static constexpr auto apply(Node1 node1, Node2 node2) {
+ return hana::and_(
+ hana::equal(node1.value, node2.value),
+ hana::equal(node1.subforest, node2.subforest)
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct transform_impl<tree_tag> {
+ template <typename Node, typename F>
+ static constexpr auto apply(Node node, F f) {
+ return make_node(
+ f(node.value),
+ hana::transform(node.subforest, [=](auto subtree) {
+ return hana::transform(subtree, f);
+ })
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Applicative
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct lift_impl<tree_tag> {
+ template <typename X>
+ static constexpr auto apply(X x)
+ { return make_node(x, make_forest()); }
+ };
+
+ template <>
+ struct ap_impl<tree_tag> {
+ template <typename F, typename X>
+ static constexpr auto apply(F f, X x) {
+ return make_node(
+ f.value(x.value),
+ hana::concat(
+ hana::transform(x.subforest, [=](auto subtree) {
+ return hana::transform(subtree, f.value);
+ }),
+ hana::transform(f.subforest, [=](auto subtree) {
+ return hana::ap(subtree, x);
+ })
+ )
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Monad
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct flatten_impl<tree_tag> {
+ template <typename Node>
+ static constexpr auto apply(Node node) {
+ return make_node(
+ node.value.value,
+ hana::concat(
+ node.value.subforest,
+ hana::transform(node.subforest, hana::flatten)
+ )
+ );
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ template <>
+ struct fold_left_impl<tree_tag> {
+ template <typename Node, typename State, typename F>
+ static constexpr auto apply(Node node, State state, F f) {
+ return hana::fold_left(node.subforest, f(state, node.value),
+ [=](auto state, auto subtree) {
+ return hana::fold_left(subtree, state, f);
+ });
+ }
+ };
+}}
+
+int main() {
+ constexpr auto tree = make_node(1, make_forest(
+ make_node(2, make_forest()),
+ make_node(3, make_forest()),
+ make_node(4, make_forest())
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::sum<>(tree) == 10);
+
+ BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
+ hana::transform(tree, [](int i) { return i + 1; }),
+ make_node(2, make_forest(
+ make_node(3, make_forest()),
+ make_node(4, make_forest()),
+ make_node(5, make_forest())
+ ))
+ ));
+}