summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/example/tutorial
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/tutorial
parentInitial commit. (diff)
downloadceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz
ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.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/tutorial')
-rw-r--r--src/boost/libs/hana/example/tutorial/algorithms.cpp148
-rw-r--r--src/boost/libs/hana/example/tutorial/appendix_mpl.cpp697
-rw-r--r--src/boost/libs/hana/example/tutorial/concepts.cpp64
-rw-r--r--src/boost/libs/hana/example/tutorial/constant_side_effects.cpp36
-rw-r--r--src/boost/libs/hana/example/tutorial/containers.cpp106
-rw-r--r--src/boost/libs/hana/example/tutorial/ext/fusion_to_hana.cpp31
-rw-r--r--src/boost/libs/hana/example/tutorial/ext/mpl_vector.cpp40
-rw-r--r--src/boost/libs/hana/example/tutorial/ext/ratio_plus.cpp15
-rw-r--r--src/boost/libs/hana/example/tutorial/include_ext.cpp16
-rw-r--r--src/boost/libs/hana/example/tutorial/integral-branching.cpp55
-rw-r--r--src/boost/libs/hana/example/tutorial/integral.cpp128
-rw-r--r--src/boost/libs/hana/example/tutorial/introduction.cpp80
-rw-r--r--src/boost/libs/hana/example/tutorial/introspection.adapt.cpp100
-rw-r--r--src/boost/libs/hana/example/tutorial/introspection.cpp158
-rw-r--r--src/boost/libs/hana/example/tutorial/introspection.json.cpp81
-rw-r--r--src/boost/libs/hana/example/tutorial/introspection.sfinae.cpp44
-rw-r--r--src/boost/libs/hana/example/tutorial/mpl_cheatsheet.cpp58
-rw-r--r--src/boost/libs/hana/example/tutorial/quickstart.cpp101
-rw-r--r--src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp105
-rw-r--r--src/boost/libs/hana/example/tutorial/rationale.container.cpp52
-rw-r--r--src/boost/libs/hana/example/tutorial/tag_dispatching.cpp170
-rw-r--r--src/boost/libs/hana/example/tutorial/type.cpp260
22 files changed, 2545 insertions, 0 deletions
diff --git a/src/boost/libs/hana/example/tutorial/algorithms.cpp b/src/boost/libs/hana/example/tutorial/algorithms.cpp
new file mode 100644
index 000000000..9afe86b1e
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/algorithms.cpp
@@ -0,0 +1,148 @@
+// 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.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+namespace hana = boost::hana;
+using namespace hana::literals;
+using namespace std::literals;
+
+
+int main() {
+
+{
+
+//! [reverse_transform]
+auto to_str = [](auto const& x) {
+ std::stringstream ss;
+ ss << x;
+ return ss.str();
+};
+
+auto xs = hana::make_tuple(1, 2.2, 'a', "bcde");
+
+BOOST_HANA_RUNTIME_CHECK(
+ hana::reverse(hana::transform(xs, to_str)) == hana::make_tuple("bcde", "a", "2.2", "1")
+);
+//! [reverse_transform]
+
+//! [reverse_transform_copy]
+hana::reverse(
+ hana::transform(xs, to_str) // <-- copy into reverse(...) here?
+);
+//! [reverse_transform_copy]
+
+//! [reverse_transform_move]
+hana::reverse(
+ hana::transform(xs, to_str) // <-- nope, move from the temporary instead!
+);
+//! [reverse_transform_move]
+
+}{
+
+//! [effects]
+auto r = hana::any_of(hana::make_tuple("hello"s, 1.2, 3), [](auto x) {
+ return std::is_integral<decltype(x)>{};
+});
+
+BOOST_HANA_CONSTANT_CHECK(r);
+//! [effects]
+
+{
+
+//! [effects.codegen]
+auto xs = hana::make_tuple("hello"s, 1.2, 3);
+auto pred = [](auto x) { return std::is_integral<decltype(x)>{}; };
+
+auto r = hana::bool_c<
+ decltype(pred(xs[0_c]))::value ? true :
+ decltype(pred(xs[1_c]))::value ? true :
+ decltype(pred(xs[2_c]))::value ? true :
+ false
+>;
+
+BOOST_HANA_CONSTANT_CHECK(r);
+//! [effects.codegen]
+
+}
+
+}{
+
+//! [cross_phase.setup]
+struct Fish { std::string name; };
+struct Cat { std::string name; };
+struct Dog { std::string name; };
+
+auto animals = hana::make_tuple(Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"});
+// ^^^^^^^ not a compile-time value
+
+BOOST_HANA_CONSTANT_CHECK(hana::length(animals) == hana::size_c<3>);
+// ^^^^^^^^^^^^^^^^^^^^^ assertion done at compile-time
+//! [cross_phase.setup]
+
+//! [cross_phase.is_empty]
+BOOST_HANA_CONSTANT_CHECK(!hana::is_empty(animals));
+// ^^^^^^^^^^^^^^^^^^^^^^^ assertion done at compile-time
+//! [cross_phase.is_empty]
+
+{
+
+//! [cross_phase.any_of_runtime]
+bool any_garfield = hana::any_of(animals, [](auto animal) {
+ return animal.name == "Garfield"s;
+});
+
+BOOST_HANA_RUNTIME_CHECK(any_garfield);
+//! [cross_phase.any_of_runtime]
+
+}{
+
+//! [cross_phase.any_of_compile_time]
+auto any_cat = hana::any_of(animals, [](auto x) {
+ return std::is_same<decltype(x), Cat>{};
+});
+
+BOOST_HANA_CONSTANT_CHECK(any_cat);
+//! [cross_phase.any_of_compile_time]
+
+}{
+
+//! [cross_phase.any_of_explicit]
+hana::integral_constant<bool, true> any_cat = hana::any_of(animals, [](auto x) {
+ return std::is_same<decltype(x), Cat>{};
+});
+
+BOOST_HANA_CONSTANT_CHECK(any_cat);
+//! [cross_phase.any_of_explicit]
+
+}{
+
+//! [cross_phase.filter]
+auto mammals = hana::filter(animals, [](auto animal) {
+ return hana::type_c<decltype(animal)> != hana::type_c<Fish>;
+});
+//! [cross_phase.filter]
+
+BOOST_HANA_RUNTIME_CHECK(
+ hana::transform(mammals, [](auto x) { return x.name; })
+ == hana::make_tuple("Garfield", "Snoopy")
+);
+
+}
+
+}{
+
+//! [cross_phase.std::tuple_size]
+std::tuple<int, char, std::string> xs{1, '2', std::string{"345"}};
+static_assert(std::tuple_size<decltype(xs)>::value == 3u, "");
+//! [cross_phase.std::tuple_size]
+
+}
+
+}
diff --git a/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp b/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp
new file mode 100644
index 000000000..3174af2ce
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/appendix_mpl.cpp
@@ -0,0 +1,697 @@
+// 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.hpp>
+#include <boost/hana/ext/boost/mpl.hpp>
+#include <boost/hana/ext/std.hpp>
+
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/quote.hpp>
+
+#include <iostream>
+#include <type_traits>
+namespace hana = boost::hana;
+namespace mpl = boost::mpl;
+
+
+namespace hpl {
+//////////////////////////////////////////////////////////////////////////////
+// Utilities
+//////////////////////////////////////////////////////////////////////////////
+namespace detail {
+ template <typename Pred>
+ constexpr auto mpl_predicate = hana::integral(hana::metafunction_class<
+ typename mpl::lambda<Pred>::type
+ >);
+
+ template <typename F>
+ constexpr auto mpl_metafunction = hana::metafunction_class<
+ typename mpl::lambda<F>::type
+ >;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// integral_c
+//////////////////////////////////////////////////////////////////////////////
+template <typename T, T v>
+using integral_c = std::integral_constant<T, v>;
+
+template <int i>
+using int_ = integral_c<int, i>;
+
+template <long i>
+using long_ = integral_c<long, i>;
+
+template <bool b>
+using bool_ = integral_c<bool, b>;
+
+using true_ = bool_<true>;
+using false_ = bool_<false>;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Sequences, compile-time integers & al
+//
+// Differences with the MPL:
+// 1. `pair<...>::first` and `pair<...>::second` won't work;
+// use `first<pair<...>>` instead
+//////////////////////////////////////////////////////////////////////////////
+template <typename ...T>
+using vector = hana::tuple<hana::type<T>...>;
+
+template <typename T, T ...v>
+using vector_c = hana::tuple<hana::integral_constant<T, v>...>;
+
+template <typename T, T from, T to>
+using range_c = decltype(hana::range_c<T, from, to>);
+
+
+template <typename T, typename U>
+using pair = hana::pair<hana::type<T>, hana::type<U>>;
+
+template <typename P>
+struct first : decltype(+hana::first(P{})) { };
+
+template <typename P>
+struct second : decltype(+hana::second(P{})) { };
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Miscellaneous metafunctions
+//////////////////////////////////////////////////////////////////////////////
+template <typename C1, typename C2>
+struct equal_to
+ : bool_<C1::value == C2::value>
+{ };
+
+template <typename C1, typename C2>
+struct less
+ : bool_<(C1::value < C2::value)>
+{ };
+
+template <typename C1, typename C2>
+struct greater
+ : bool_<(C1::value > C2::value)>
+{ };
+
+template <typename N>
+struct next
+ : integral_c<typename N::value_type, N::value + 1>
+{ };
+
+//////////////////////////////////////////////////////////////////////////////
+// Intrinsics
+//
+// Differences with the MPL:
+// 1. `at` does not work for associative sequences; use `find` instead.
+// 2. `begin`, `end`, `clear`, `erase`, `erase_key`, `insert`, `insert_range`,
+// `is_sequence`, `key_type`, `order`, `sequence_tag`, `value_type`: not implemented
+//////////////////////////////////////////////////////////////////////////////
+template <typename Sequence, typename N>
+struct at
+ : decltype(hana::at(Sequence{}, N{}))
+{ };
+
+template <typename Sequence, long n>
+using at_c = at<Sequence, long_<n>>;
+
+template <typename Sequence>
+struct back
+ : decltype(+hana::back(Sequence{}))
+{ };
+
+template <typename Sequence>
+struct empty
+ : decltype(hana::is_empty(Sequence{}))
+{ };
+
+template <typename Sequence>
+struct front
+ : decltype(+hana::front(Sequence{}))
+{ };
+
+template <typename Sequence>
+struct pop_back {
+ using type = decltype(hana::drop_back(
+ hana::to_tuple(Sequence{}), hana::size_c<1>
+ ));
+};
+
+template <typename Sequence>
+struct pop_front {
+ using type = decltype(hana::drop_front(Sequence{}));
+};
+
+template <typename Sequence, typename T>
+struct push_back {
+ using type = decltype(hana::append(Sequence{}, hana::type_c<T>));
+};
+
+template <typename Sequence, typename T>
+struct push_front {
+ using type = decltype(hana::prepend(Sequence{}, hana::type_c<T>));
+};
+
+template <typename Sequence>
+struct size
+ : decltype(hana::length(Sequence{}))
+{ };
+
+//////////////////////////////////////////////////////////////////////////////
+// Iteration algorithms
+//
+// Differences with the MPL:
+// 1. reverse_fold:
+// Does not take an optional additional ForwardOp argument.
+//
+// 2. iter_fold, reverse_iter_fold:
+// Not implemented because we don't use iterators
+//////////////////////////////////////////////////////////////////////////////
+template <typename Sequence, typename State, typename F>
+struct fold
+ : decltype(hana::fold(
+ Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
+ ))
+{ };
+
+template <typename Sequence, typename State, typename F>
+struct reverse_fold
+ : decltype(hana::reverse_fold(
+ Sequence{}, hana::type_c<State>, detail::mpl_metafunction<F>
+ ))
+{ };
+
+template <typename Sequence, typename State, typename F>
+using accumulate = fold<Sequence, State, F>;
+
+//////////////////////////////////////////////////////////////////////////////
+// Query algorithms
+//
+// Differences with the MPL:
+// 1. find_if and find:
+// Instead of returning an iterator, they either have a nested `::type`
+// alias to the answer, or they have no nested `::type` at all, which
+// makes them SFINAE-friendly.
+//
+// 2. lower_bound, upper_bound:
+// Not implemented.
+//
+// 3. {min,max}_element:
+// Not returning an iterator, and also won't work on empty sequences.
+//////////////////////////////////////////////////////////////////////////////
+template <typename Sequence, typename Pred>
+struct find_if
+ : decltype(hana::find_if(Sequence{}, detail::mpl_predicate<Pred>))
+{ };
+
+template <typename Sequence, typename T>
+struct find
+ : decltype(hana::find(Sequence{}, hana::type_c<T>))
+{ };
+
+template <typename Sequence, typename T>
+struct contains
+ : decltype(hana::contains(Sequence{}, hana::type_c<T>))
+{ };
+
+template <typename Sequence, typename T>
+struct count
+ : decltype(hana::count(Sequence{}, hana::type_c<T>))
+{ };
+
+template <typename Sequence, typename Pred>
+struct count_if
+ : decltype(hana::count_if(Sequence{}, detail::mpl_predicate<Pred>))
+{ };
+
+template <typename Sequence, typename Pred = mpl::quote2<less>>
+struct min_element
+ : decltype(hana::minimum(Sequence{}, detail::mpl_predicate<Pred>))
+{ };
+
+template <typename Sequence, typename Pred = mpl::quote2<less>>
+struct max_element
+ : decltype(hana::maximum(Sequence{}, detail::mpl_predicate<Pred>))
+{ };
+
+template <typename S1, typename S2, typename Pred = mpl::quote2<std::is_same>>
+struct equal
+ : decltype( // inefficient but whatever
+ hana::length(S1{}) == hana::length(S2{}) &&
+ hana::all(hana::zip_shortest_with(detail::mpl_predicate<Pred>,
+ hana::to_tuple(S1{}),
+ hana::to_tuple(S2{})))
+ )
+{ };
+
+//////////////////////////////////////////////////////////////////////////////
+// Transformation algorithms
+//
+// Differences from the MPL:
+// 1. The algorithms do not accept an optional inserter, and they always
+// return a `vector`.
+// 2. stable_partition: not implemented
+// 3. All the reverse_* algorithms are not implemented.
+//////////////////////////////////////////////////////////////////////////////
+template <typename Sequence>
+struct copy {
+ using type = decltype(hana::to_tuple(Sequence{}));
+};
+
+template <typename Sequence, typename Pred>
+struct copy_if {
+ using type = decltype(hana::filter(
+ hana::to_tuple(Sequence{}),
+ detail::mpl_predicate<Pred>
+ ));
+};
+
+template <typename Sequence, typename Sequence_or_Op, typename = void>
+struct transform;
+
+template <typename Sequence, typename Op>
+struct transform<Sequence, Op> {
+ using type = decltype(hana::transform(
+ hana::to_tuple(Sequence{}), detail::mpl_metafunction<Op>
+ ));
+};
+
+template <typename S1, typename S2, typename Op>
+struct transform {
+ using type = decltype(hana::zip_with(
+ detail::mpl_metafunction<Op>,
+ hana::to_tuple(S1{}),
+ hana::to_tuple(S2{})
+ ));
+};
+
+template <typename Sequence, typename OldType, typename NewType>
+struct replace {
+ using type = decltype(hana::replace(
+ hana::to_tuple(Sequence{}),
+ hana::type_c<OldType>,
+ hana::type_c<NewType>
+ ));
+};
+
+template <typename Sequence, typename Pred, typename NewType>
+struct replace_if {
+ using type = decltype(hana::replace_if(
+ hana::to_tuple(Sequence{}),
+ detail::mpl_predicate<Pred>,
+ hana::type_c<NewType>
+ ));
+};
+
+template <typename Sequence, typename T>
+struct remove {
+ using type = decltype(hana::filter(
+ hana::to_tuple(Sequence{}),
+ hana::not_equal.to(hana::type_c<T>)
+ ));
+};
+
+template <typename Sequence, typename Pred>
+struct remove_if {
+ using type = decltype(hana::filter(
+ hana::to_tuple(Sequence{}),
+ hana::compose(hana::not_, detail::mpl_predicate<Pred>)
+ ));
+};
+
+template <typename Sequence, typename Pred>
+struct unique {
+ using type = decltype(hana::unique(
+ hana::to_tuple(Sequence{}),
+ detail::mpl_predicate<Pred>
+ ));
+};
+
+template <typename Sequence, typename Pred>
+struct partition {
+ using hana_pair = decltype(hana::partition(
+ hana::to_tuple(Sequence{}),
+ detail::mpl_predicate<Pred>
+ ));
+ using type = pair<
+ decltype(hana::first(hana_pair{})),
+ decltype(hana::second(hana_pair{}))
+ >;
+};
+
+template <typename Sequence, typename Pred = mpl::quote2<less>>
+struct sort {
+ using type = decltype(hana::sort(
+ hana::to_tuple(Sequence{}), detail::mpl_predicate<Pred>
+ ));
+};
+
+template <typename Sequence>
+struct reverse {
+ using type = decltype(hana::reverse(hana::to_tuple(Sequence{})));
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Runtime algorithms
+//////////////////////////////////////////////////////////////////////////////
+template <typename Sequence, typename F>
+void for_each(F f) {
+ hana::for_each(Sequence{}, [&f](auto t) {
+ f(typename decltype(t)::type{});
+ });
+}
+
+template <typename Sequence, typename TransformOp, typename F>
+void for_each(F f) {
+ for_each<typename transform<Sequence, TransformOp>::type>(f);
+}
+
+} // end namespace hpl
+
+
+template <typename N>
+struct is_odd
+ : hpl::bool_<(N::value % 2)>
+{ };
+
+
+int main() {
+using namespace hpl;
+
+//////////////////////////////////////////////////////////////////////////////
+// Misc
+//////////////////////////////////////////////////////////////////////////////
+
+// pair
+{
+ static_assert(std::is_same<first<pair<int, float>>::type, int>{}, "");
+ static_assert(std::is_same<second<pair<int, float>>::type, float>{}, "");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Intrinsics
+//////////////////////////////////////////////////////////////////////////////
+
+// at
+{
+ using range = range_c<long,10,50>;
+ static_assert(at<range, int_<0>>::value == 10, "");
+ static_assert(at<range, int_<10>>::value == 20, "");
+ static_assert(at<range, int_<40>>::value == 50, "");
+}
+
+// at_c
+{
+ using range = range_c<long, 10, 50>;
+ static_assert(at_c<range, 0>::value == 10, "");
+ static_assert(at_c<range, 10>::value == 20, "");
+ static_assert(at_c<range, 40>::value == 50, "");
+}
+
+// back
+{
+ using range1 = range_c<int,0,1>;
+ using range2 = range_c<int,0,10>;
+ using range3 = range_c<int,-10,0>;
+ using types = vector<int, char, float>;
+ static_assert(back<range1>::value == 0, "");
+ static_assert(back<range2>::value == 9, "");
+ static_assert(back<range3>::value == -1, "");
+ static_assert(std::is_same<back<types>::type, float>{}, "");
+}
+
+// empty
+{
+ using empty_range = range_c<int,0,0>;
+ using types = vector<long,float,double>;
+ static_assert(empty<empty_range>{}, "");
+ static_assert(!empty<types>{}, "");
+}
+
+// front
+{
+ using types1 = vector<long>;
+ using types2 = vector<int,long>;
+ using types3 = vector<char,int,long>;
+ static_assert(std::is_same<front<types1>::type, long>{}, "");
+ static_assert(std::is_same<front<types2>::type, int>{}, "");
+ static_assert(std::is_same<front<types3>::type, char>{}, "");
+}
+
+// pop_back
+{
+ using types1 = vector<long>;
+ using types2 = vector<long,int>;
+ using types3 = vector<long,int,char>;
+
+
+ using result1 = pop_back<types1>::type;
+ using result2 = pop_back<types2>::type;
+ using result3 = pop_back<types3>::type;
+
+ static_assert(size<result1>::value == 0, "");
+ static_assert(size<result2>::value == 1, "");
+ static_assert(size<result3>::value == 2, "");
+
+ static_assert(std::is_same< back<result2>::type, long>{}, "");
+ static_assert(std::is_same< back<result3>::type, int>{}, "");
+}
+
+// pop_front
+{
+ using types1 = vector<long>;
+ using types2 = vector<int,long>;
+ using types3 = vector<char,int,long>;
+
+ using result1 = pop_front<types1>::type;
+ using result2 = pop_front<types2>::type;
+ using result3 = pop_front<types3>::type;
+
+ static_assert(size<result1>::value == 0, "");
+ static_assert(size<result2>::value == 1, "");
+ static_assert(size<result3>::value == 2, "");
+
+ static_assert(std::is_same<front<result2>::type, long>{}, "");
+ static_assert(std::is_same<front<result3>::type, int>{}, "");
+}
+
+// push_back
+{
+ using bools = vector_c<bool,false,false,false,true,true,true,false,false>;
+ using message = push_back<bools, false_>::type;
+ static_assert(back<message>::type::value == false, "");
+ static_assert(count_if<message, equal_to<mpl::_1, false_>>{} == 6u, "");
+}
+
+// push_front
+{
+ using v = vector_c<int,1,2,3,5,8,13,21>;
+ static_assert(size<v>{} == 7u, "");
+
+ using fibonacci = push_front<v, int_<1>>::type;
+ static_assert(size<fibonacci>{} == 8u, "");
+
+ static_assert(equal<
+ fibonacci,
+ vector_c<int,1,1,2,3,5,8,13,21>,
+ equal_to<mpl::_, mpl::_>
+ >{}, "");
+}
+
+// size
+{
+ using empty_list = vector<>;
+ using numbers = vector_c<int,0,1,2,3,4,5>;
+ using more_numbers = range_c<int,0,100>;
+
+ static_assert(size<empty_list>{} == 0u, "");
+ static_assert(size<numbers>{} == 6u, "");
+ static_assert(size<more_numbers>{} == 100u, "");
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Iteration algorithms
+//////////////////////////////////////////////////////////////////////////////
+
+// fold
+{
+ using types = vector<long,float,short,double,float,long,long double>;
+ using number_of_floats = fold<types, int_<0>,
+ mpl::if_<std::is_floating_point<mpl::_2>,
+ next<mpl::_1>,
+ mpl::_1
+ >
+ >::type;
+ static_assert(number_of_floats{} == 4, "");
+}
+
+// reverse_fold
+{
+ using numbers = vector_c<int,5,-1,0,-7,-2,0,-5,4>;
+ using negatives = vector_c<int,-1,-7,-2,-5>;
+ using result = reverse_fold<numbers, vector_c<int>,
+ mpl::if_<less<mpl::_2, int_<0>>,
+ push_front<mpl::_1, mpl::_2>,
+ mpl::_1
+ >
+ >::type;
+ static_assert(equal<negatives, result>{}, "");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Query algorithms
+//////////////////////////////////////////////////////////////////////////////
+
+// find_if
+{
+ using types = vector<char,int,unsigned,long,unsigned long>;
+ using found = find_if<types, std::is_same<mpl::_1, unsigned>>::type;
+ static_assert(std::is_same<found, unsigned>{}, "");
+}
+
+// find
+{
+ using types = vector<char,int,unsigned,long,unsigned long>;
+ static_assert(std::is_same<find<types, unsigned>::type, unsigned>{}, "");
+}
+
+// contains
+{
+ using types = vector<char,int,unsigned,long,unsigned long>;
+ static_assert(!contains<types, bool>{}, "");
+}
+
+// count
+{
+ using types = vector<int,char,long,short,char,short,double,long>;
+ static_assert(count<types, short>{} == 2u, "");
+}
+
+// count_if
+{
+ using types = vector<int,char,long,short,char,long,double,long>;
+ static_assert(count_if<types, std::is_floating_point<mpl::_>>{} == 1u, "");
+ static_assert(count_if<types, std::is_same<mpl::_, char>>{} == 2u, "");
+ static_assert(count_if<types, std::is_same<mpl::_, void>>{} == 0u, "");
+}
+
+// min_element (MPL's example is completely broken)
+{
+}
+
+// max_element (MPL's example is completely broken)
+{
+}
+
+// equal
+{
+ using s1 = vector<char,int,unsigned,long,unsigned long>;
+ using s2 = vector<char,int,unsigned,long>;
+ static_assert(!equal<s1,s2>{}, "");
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Transformaton algorithms
+//////////////////////////////////////////////////////////////////////////////
+// copy
+{
+ using numbers = vector_c<int,10, 11, 12, 13, 14, 15, 16, 17, 18, 19>;
+ using result = copy<range_c<int, 10, 20>>::type;
+ static_assert(size<result>{} == 10u, "");
+ static_assert(equal<result, numbers, mpl::quote2<equal_to>>{}, "");
+}
+
+// copy_if
+{
+ using result = copy_if<range_c<int, 0, 10>, less<mpl::_1, int_<5>>>::type;
+ static_assert(size<result>{} == 5u, "");
+ static_assert(equal<result, range_c<int, 0, 5>>{}, "");
+}
+
+// transform
+{
+ using types = vector<char,short,int,long,float,double>;
+ using pointers = vector<char*,short*,int*,long*,float*,double*>;
+ using result = transform<types,std::add_pointer<mpl::_1>>::type;
+ static_assert(equal<result, pointers>{}, "");
+}
+
+// replace
+{
+ using types = vector<int,float,char,float,float,double>;
+ using expected = vector<int,double,char,double,double,double>;
+ using result = replace< types,float,double >::type;
+ static_assert(equal<result, expected>{}, "");
+}
+
+// replace_if
+{
+ using numbers = vector_c<int,1,4,5,2,7,5,3,5>;
+ using expected = vector_c<int,1,4,0,2,0,0,3,0>;
+ using result = replace_if<numbers, greater<mpl::_, int_<4>>, int_<0>>::type;
+ static_assert(equal<result, expected, mpl::quote2<equal_to>>{}, "");
+}
+
+// remove
+{
+ using types = vector<int,float,char,float,float,double>;
+ using result = hpl::remove<types, float>::type;
+ static_assert(equal<result, vector<int, char, double>>{}, "");
+}
+
+// remove_if
+{
+ using numbers = vector_c<int,1,4,5,2,7,5,3,5>;
+ using result = remove_if<numbers, greater<mpl::_, int_<4> > >::type;
+ static_assert(equal<result, vector_c<int,1,4,2,3>, mpl::quote2<equal_to>>{}, "");
+}
+
+// unique
+{
+ using types = vector<int,float,float,char,int,int,int,double>;
+ using expected = vector<int,float,char,int,double>;
+ using result = unique<types, std::is_same<mpl::_1, mpl::_2>>::type;
+ static_assert(equal<result, expected>{}, "");
+}
+
+// partition
+{
+ using r = partition<range_c<int,0,10>, is_odd<mpl::_1>>::type;
+ static_assert(equal<first<r>::type, vector_c<int,1,3,5,7,9>>{}, "");
+ static_assert(equal<second<r>::type, vector_c<int,0,2,4,6,8>>{}, "");
+}
+
+// sort
+{
+ using numbers = vector_c<int,3,4,0,-5,8,-1,7>;
+ using expected = vector_c<int,-5,-1,0,3,4,7,8>;
+ using result = sort<numbers>::type;
+ static_assert(equal<result, expected, equal_to<mpl::_, mpl::_>>{}, "");
+}
+
+// reverse
+{
+ using numbers = vector_c<int,9,8,7,6,5,4,3,2,1,0>;
+ using result = reverse<numbers>::type;
+ static_assert(equal<result, range_c<int,0,10>>{}, "");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Runtime algorithms
+//////////////////////////////////////////////////////////////////////////////
+
+// for_each
+{
+ auto value_printer = [](auto x) {
+ std::cout << x << '\n';
+ };
+
+ for_each<range_c<int, 0, 10> >(value_printer);
+}
+
+}
diff --git a/src/boost/libs/hana/example/tutorial/concepts.cpp b/src/boost/libs/hana/example/tutorial/concepts.cpp
new file mode 100644
index 000000000..751b47309
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/concepts.cpp
@@ -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)
+
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/integral_constant.hpp>
+
+#include <string>
+#include <type_traits>
+namespace hana = boost::hana;
+
+
+namespace with_special_base_class {
+//! [special_base_class]
+struct special_base_class { };
+
+template <typename T>
+struct print_impl : special_base_class {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+};
+
+template <typename T>
+struct Printable
+ : hana::integral_constant<bool,
+ !std::is_base_of<special_base_class, print_impl<hana::tag_of_t<T>>>::value
+ >
+{ };
+//! [special_base_class]
+
+//! [special_base_class_customize]
+struct Person { std::string name; };
+
+template <>
+struct print_impl<Person> /* don't inherit from special_base_class */ {
+ // ... implementation ...
+};
+
+static_assert(Printable<Person>::value, "");
+static_assert(!Printable<void>::value, "");
+//! [special_base_class_customize]
+}
+
+namespace actual {
+//! [actual]
+template <typename T>
+struct print_impl : hana::default_ {
+ template <typename ...Args>
+ static constexpr auto apply(Args&& ...) = delete;
+};
+
+template <typename T>
+struct Printable
+ : hana::integral_constant<bool,
+ !hana::is_default<print_impl<hana::tag_of_t<T>>>::value
+ >
+{ };
+//! [actual]
+
+static_assert(!Printable<void>::value, "");
+}
+
+int main() { }
diff --git a/src/boost/libs/hana/example/tutorial/constant_side_effects.cpp b/src/boost/libs/hana/example/tutorial/constant_side_effects.cpp
new file mode 100644
index 000000000..ea81ec08e
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/constant_side_effects.cpp
@@ -0,0 +1,36 @@
+// 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 <iostream>
+namespace hana = boost::hana;
+
+
+namespace pure {
+//! [pure]
+template <typename X>
+auto identity(X x) { return x; }
+
+auto x = identity(hana::bool_c<true>);
+static_assert(hana::value(x), "");
+//! [pure]
+}
+
+namespace impure {
+//! [impure_identity]
+template <typename X>
+auto identity(X x) {
+ std::cout << "Good luck in evaluating this at compile-time!";
+ return x;
+}
+//! [impure_identity]
+
+//! [impure]
+auto x = identity(hana::bool_c<true>);
+static_assert(hana::value(x), "");
+//! [impure]
+}
+
+int main() { }
diff --git a/src/boost/libs/hana/example/tutorial/containers.cpp b/src/boost/libs/hana/example/tutorial/containers.cpp
new file mode 100644
index 000000000..fe9242704
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/containers.cpp
@@ -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)
+
+#include <boost/hana.hpp>
+
+#include <functional>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+namespace hana = boost::hana;
+using namespace hana::literals;
+using namespace std::literals;
+
+
+int main() {
+
+{
+
+//! [make<tuple_tag>]
+auto xs = hana::make<hana::tuple_tag>(1, 2.2, 'a', "bcde"s);
+//! [make<tuple_tag>]
+
+}{
+
+//! [make<range_tag>]
+constexpr auto r = hana::make<hana::range_tag>(hana::int_c<3>, hana::int_c<10>);
+static_assert(r == hana::make_range(hana::int_c<3>, hana::int_c<10>), "");
+//! [make<range_tag>]
+
+}{
+
+//! [tuple_constructor]
+hana::tuple<int, double, char, std::string> xs{1, 2.2, 'a', "bcde"s};
+//! [tuple_constructor]
+(void)xs;
+
+}{
+
+//! [types]
+auto xs = hana::make_tuple(1, '2', "345");
+auto ints = hana::make_range(hana::int_c<0>, hana::int_c<100>);
+// what can we say about the types of `xs` and `ints`?
+//! [types]
+(void)xs;
+(void)ints;
+
+}{
+
+//! [types_maximally_specified]
+hana::tuple<int, char, char const*> xs = hana::make_tuple(1, '2', "345");
+auto ints = hana::make_range(hana::int_c<0>, hana::int_c<100>);
+// can't specify the type of ints, however
+//! [types_maximally_specified]
+(void)xs;
+(void)ints;
+
+}{
+
+//! [lifetime]
+std::string hello = "Hello";
+std::vector<char> world = {'W', 'o', 'r', 'l', 'd'};
+
+// hello is copied, world is moved-in
+auto xs = hana::make_tuple(hello, std::move(world));
+
+// s is a reference to the copy of hello inside xs.
+// It becomes a dangling reference as soon as xs is destroyed.
+std::string& s = xs[0_c];
+//! [lifetime]
+(void)s;
+
+}{
+
+//! [reference_wrapper]
+std::vector<int> ints = { /* huge vector of ints */ };
+std::vector<std::string> strings = { /* huge vector of strings */ };
+
+auto map = hana::make_map(
+ hana::make_pair(hana::type_c<int>, std::ref(ints)),
+ hana::make_pair(hana::type_c<std::string>, std::ref(strings))
+);
+
+auto& v = map[hana::type_c<int>].get();
+BOOST_HANA_RUNTIME_CHECK(&v == &ints);
+//! [reference_wrapper]
+
+}
+
+}
+
+
+namespace overloading {
+//! [overloading]
+template <typename T>
+void f(std::vector<T> xs) {
+ // ...
+}
+
+template <typename R, typename = std::enable_if_t<hana::is_a<hana::range_tag, R>()>>
+void f(R r) {
+ // ...
+}
+//! [overloading]
+}
diff --git a/src/boost/libs/hana/example/tutorial/ext/fusion_to_hana.cpp b/src/boost/libs/hana/example/tutorial/ext/fusion_to_hana.cpp
new file mode 100644
index 000000000..8b6a334d4
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/ext/fusion_to_hana.cpp
@@ -0,0 +1,31 @@
+// 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/for_each.hpp>
+#include <boost/hana/tuple.hpp>
+#include <boost/hana/ext/boost/fusion/vector.hpp>
+
+#include <boost/fusion/include/vector.hpp>
+
+#include <iostream>
+namespace fusion = boost::fusion;
+namespace hana = boost::hana;
+
+
+//! [main]
+// In the old code, this used to receive a Fusion sequence.
+// Now, it can be either a Hana sequence or a Fusion sequence.
+template <typename Sequence>
+void f(Sequence const& seq) {
+ hana::for_each(seq, [](auto const& element) {
+ std::cout << element << std::endl;
+ });
+}
+//! [main]
+
+
+int main() {
+ f(hana::make_tuple(1, 2, 3));
+ f(fusion::make_vector(1, 2, 3));
+}
diff --git a/src/boost/libs/hana/example/tutorial/ext/mpl_vector.cpp b/src/boost/libs/hana/example/tutorial/ext/mpl_vector.cpp
new file mode 100644
index 000000000..2802bafe6
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/ext/mpl_vector.cpp
@@ -0,0 +1,40 @@
+// 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/front.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/type.hpp>
+
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/vector.hpp>
+namespace hana = boost::hana;
+namespace mpl = boost::mpl;
+
+
+//! [front]
+#include <boost/hana/ext/boost/mpl/vector.hpp> // bridge header
+
+using Vector = mpl::vector<int, char, float>;
+static_assert(hana::front(Vector{}) == hana::type_c<int>, "");
+//! [front]
+
+
+namespace _ns0 {
+//! [size]
+using Size = mpl::size<Vector>::type;
+static_assert(hana::equal(Size{}, hana::int_c<3>), ""); // breaks!
+//! [size]
+}
+
+
+//! [size-fixed]
+#include <boost/hana/ext/boost/mpl/integral_c.hpp>
+
+using Size = mpl::size<Vector>::type;
+static_assert(hana::equal(Size{}, hana::int_c<3>), "");
+//! [size-fixed]
+
+
+int main() { }
diff --git a/src/boost/libs/hana/example/tutorial/ext/ratio_plus.cpp b/src/boost/libs/hana/example/tutorial/ext/ratio_plus.cpp
new file mode 100644
index 000000000..e3c15546f
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/ext/ratio_plus.cpp
@@ -0,0 +1,15 @@
+// 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)
+
+//! [main]
+#include <boost/hana/ext/std/ratio.hpp>
+#include <boost/hana/plus.hpp>
+
+#include <ratio>
+namespace hana = boost::hana;
+
+auto r = hana::plus(std::ratio<3, 4>{}, std::ratio<4, 5>{});
+//! [main]
+
+int main() { }
diff --git a/src/boost/libs/hana/example/tutorial/include_ext.cpp b/src/boost/libs/hana/example/tutorial/include_ext.cpp
new file mode 100644
index 000000000..d753d6249
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/include_ext.cpp
@@ -0,0 +1,16 @@
+// 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)
+
+//! [main]
+#include <boost/hana/ext/std/tuple.hpp>
+#include <boost/hana/front.hpp>
+#include <tuple> // still required to create a tuple
+namespace hana = boost::hana;
+
+
+int main() {
+ constexpr std::tuple<int, char, float> xs{1, '2', 3.0f};
+ static_assert(hana::front(xs) == 1, "");
+}
+//! [main]
diff --git a/src/boost/libs/hana/example/tutorial/integral-branching.cpp b/src/boost/libs/hana/example/tutorial/integral-branching.cpp
new file mode 100644
index 000000000..7e93f9402
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/integral-branching.cpp
@@ -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)
+
+#include <boost/hana.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
+namespace hana = boost::hana;
+
+
+
+namespace ns1 {
+//! [make_unique.if_]
+template <typename T, typename ...Args>
+std::unique_ptr<T> make_unique(Args&&... args) {
+ return hana::if_(std::is_constructible<T, Args...>{},
+ [](auto&& ...x) { return std::unique_ptr<T>(new T(std::forward<Args>(x)...)); },
+ [](auto&& ...x) { return std::unique_ptr<T>(new T{std::forward<Args>(x)...}); }
+ )(std::forward<Args>(args)...);
+}
+//! [make_unique.if_]
+}
+
+
+namespace ns2 {
+//! [make_unique.eval_if]
+template <typename T, typename ...Args>
+std::unique_ptr<T> make_unique(Args&&... args) {
+ return hana::eval_if(std::is_constructible<T, Args...>{},
+ [&](auto _) { return std::unique_ptr<T>(new T(std::forward<Args>(_(args))...)); },
+ [&](auto _) { return std::unique_ptr<T>(new T{std::forward<Args>(_(args))...}); }
+ );
+}
+//! [make_unique.eval_if]
+}
+
+struct Student {
+ std::string name;
+ int age;
+};
+
+int main() {
+ {
+ std::unique_ptr<int> a = ns1::make_unique<int>(3);
+ std::unique_ptr<Student> b = ns1::make_unique<Student>("Bob", 25);
+ }
+ {
+ std::unique_ptr<int> a = ns2::make_unique<int>(3);
+ std::unique_ptr<Student> b = ns2::make_unique<Student>("Bob", 25);
+ }
+}
diff --git a/src/boost/libs/hana/example/tutorial/integral.cpp b/src/boost/libs/hana/example/tutorial/integral.cpp
new file mode 100644
index 000000000..be285c560
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/integral.cpp
@@ -0,0 +1,128 @@
+// 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/mpl/equal_to.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/minus.hpp>
+#include <boost/mpl/multiplies.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/plus.hpp>
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/pair.hpp>
+#include <boost/hana/plus.hpp>
+
+#include <type_traits>
+namespace hana = boost::hana;
+
+
+namespace support {
+template <typename T, typename = std::enable_if_t<
+ !hana::Constant<T>::value
+>>
+constexpr T sqrt(T x) {
+ T inf = 0, sup = (x == 1 ? 1 : x/2);
+ while (!((sup - inf) <= 1 || ((sup*sup <= x) && ((sup+1)*(sup+1) > x)))) {
+ T mid = (inf + sup) / 2;
+ bool take_inf = mid*mid > x ? 1 : 0;
+ inf = take_inf ? inf : mid;
+ sup = take_inf ? mid : sup;
+ }
+
+ return sup*sup <= x ? sup : inf;
+}
+
+template <typename T, typename = std::enable_if_t<
+ hana::Constant<T>::value
+>>
+constexpr auto sqrt(T const&) {
+ return hana::integral_c<typename T::value_type, sqrt(T::value)>;
+}
+} // end namespace support
+
+
+namespace then {
+namespace mpl = boost::mpl;
+
+template <typename N>
+struct sqrt
+ : mpl::integral_c<typename N::value_type, support::sqrt(N::value)>
+{ };
+
+template <typename X, typename Y>
+struct point {
+ using x = X;
+ using y = Y;
+};
+
+//! [distance-mpl]
+template <typename P1, typename P2>
+struct distance {
+ using xs = typename mpl::minus<typename P1::x,
+ typename P2::x>::type;
+ using ys = typename mpl::minus<typename P1::y,
+ typename P2::y>::type;
+ using type = typename sqrt<
+ typename mpl::plus<
+ typename mpl::multiplies<xs, xs>::type,
+ typename mpl::multiplies<ys, ys>::type
+ >::type
+ >::type;
+};
+
+static_assert(mpl::equal_to<
+ distance<point<mpl::int_<3>, mpl::int_<5>>,
+ point<mpl::int_<7>, mpl::int_<2>>>::type,
+ mpl::int_<5>
+>::value, "");
+//! [distance-mpl]
+}
+
+
+namespace now {
+namespace hana = boost::hana;
+using namespace hana::literals;
+
+template <typename X, typename Y>
+struct _point {
+ X x;
+ Y y;
+};
+template <typename X, typename Y>
+constexpr _point<X, Y> point(X x, Y y) { return {x, y}; }
+
+using support::sqrt; // avoid conflicts with ::sqrt
+
+//! [distance-hana]
+template <typename P1, typename P2>
+constexpr auto distance(P1 p1, P2 p2) {
+ auto xs = p1.x - p2.x;
+ auto ys = p1.y - p2.y;
+ return sqrt(xs*xs + ys*ys);
+}
+
+BOOST_HANA_CONSTANT_CHECK(distance(point(3_c, 5_c), point(7_c, 2_c)) == 5_c);
+//! [distance-hana]
+
+void test() {
+
+//! [distance-dynamic]
+auto p1 = point(3, 5); // dynamic values now
+auto p2 = point(7, 2); //
+BOOST_HANA_RUNTIME_CHECK(distance(p1, p2) == 5); // same function works!
+//! [distance-dynamic]
+
+}
+}
+
+
+int main() {
+ now::test();
+}
diff --git a/src/boost/libs/hana/example/tutorial/introduction.cpp b/src/boost/libs/hana/example/tutorial/introduction.cpp
new file mode 100644
index 000000000..1cafff047
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introduction.cpp
@@ -0,0 +1,80 @@
+// 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)
+
+// Make sure `assert` always triggers an assertion
+#ifdef NDEBUG
+# undef NDEBUG
+#endif
+
+#include <boost/fusion/include/comparison.hpp>
+#include <boost/fusion/include/make_vector.hpp>
+#include <boost/fusion/include/transform.hpp>
+#include <boost/fusion/include/vector.hpp>
+
+#include <boost/mpl/equal.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+namespace fusion = boost::fusion;
+namespace mpl = boost::mpl;
+using namespace std::literals;
+
+
+int main() {
+
+{
+
+//! [runtime]
+auto f = [](int i) -> std::string {
+ return std::to_string(i * i);
+};
+
+std::vector<int> ints{1, 2, 3, 4};
+std::vector<std::string> strings;
+std::transform(ints.begin(), ints.end(), std::back_inserter(strings), f);
+
+assert((strings == std::vector<std::string>{"1", "4", "9", "16"}));
+//! [runtime]
+
+}{
+
+//! [heterogeneous]
+auto to_string = [](auto t) {
+ std::stringstream ss;
+ ss << t;
+ return ss.str();
+};
+
+fusion::vector<int, std::string, float> seq{1, "abc", 3.4f};
+fusion::vector<std::string, std::string, std::string>
+ strings = fusion::transform(seq, to_string);
+
+assert(strings == fusion::make_vector("1"s, "abc"s, "3.4"s));
+//! [heterogeneous]
+
+}
+
+}
+
+//! [type-level]
+template <typename T>
+struct add_const_pointer {
+ using type = T const*;
+};
+
+using types = mpl::vector<int, char, float, void>;
+using pointers = mpl::transform<types, add_const_pointer<mpl::_1>>::type;
+
+static_assert(mpl::equal<
+ pointers,
+ mpl::vector<int const*, char const*, float const*, void const*>
+>::value, "");
+//! [type-level]
diff --git a/src/boost/libs/hana/example/tutorial/introspection.adapt.cpp b/src/boost/libs/hana/example/tutorial/introspection.adapt.cpp
new file mode 100644
index 000000000..bfdf4453c
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introspection.adapt.cpp
@@ -0,0 +1,100 @@
+// 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.hpp>
+
+#include <iostream>
+#include <string>
+namespace hana = boost::hana;
+using namespace hana::literals;
+using namespace std::literals;
+
+
+//! [BOOST_HANA_DEFINE_STRUCT]
+struct Person {
+ BOOST_HANA_DEFINE_STRUCT(Person,
+ (std::string, name),
+ (int, age)
+ );
+};
+//! [BOOST_HANA_DEFINE_STRUCT]
+
+int main() {
+
+//! [for_each]
+Person john{"John", 30};
+
+hana::for_each(john, [](auto pair) {
+ std::cout << hana::to<char const*>(hana::first(pair)) << ": "
+ << hana::second(pair) << std::endl;
+});
+
+// name: John
+// age: 30
+//! [for_each]
+
+//! [for_each.fuse]
+hana::for_each(john, hana::fuse([](auto name, auto member) {
+ std::cout << hana::to<char const*>(name) << ": " << member << std::endl;
+}));
+//! [for_each.fuse]
+
+#ifdef BOOST_HANA_CONFIG_ENABLE_STRING_UDL
+
+{
+
+//! [at_key]
+std::string name = hana::at_key(john, "name"_s);
+BOOST_HANA_RUNTIME_CHECK(name == "John");
+
+int age = hana::at_key(john, "age"_s);
+BOOST_HANA_RUNTIME_CHECK(age == 30);
+//! [at_key]
+
+}{
+
+//! [to<map_tag>]
+auto map = hana::insert(hana::to<hana::map_tag>(john), hana::make_pair("last name"_s, "Doe"s));
+
+std::string name = map["name"_s];
+BOOST_HANA_RUNTIME_CHECK(name == "John");
+
+std::string last_name = map["last name"_s];
+BOOST_HANA_RUNTIME_CHECK(last_name == "Doe");
+
+int age = map["age"_s];
+BOOST_HANA_RUNTIME_CHECK(age == 30);
+//! [to<map_tag>]
+
+}
+
+#endif
+
+}
+
+//! [BOOST_HANA_ADAPT_STRUCT]
+namespace not_my_namespace {
+ struct Person {
+ std::string name;
+ int age;
+ };
+}
+
+BOOST_HANA_ADAPT_STRUCT(not_my_namespace::Person, name, age);
+//! [BOOST_HANA_ADAPT_STRUCT]
+
+
+//! [BOOST_HANA_ADAPT_ADT]
+namespace also_not_my_namespace {
+ struct Person {
+ std::string get_name();
+ int get_age();
+ };
+}
+
+BOOST_HANA_ADAPT_ADT(also_not_my_namespace::Person,
+ (name, [](auto const& p) { return p.get_name(); }),
+ (age, [](auto const& p) { return p.get_age(); })
+);
+//! [BOOST_HANA_ADAPT_ADT]
diff --git a/src/boost/libs/hana/example/tutorial/introspection.cpp b/src/boost/libs/hana/example/tutorial/introspection.cpp
new file mode 100644
index 000000000..3b72db447
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introspection.cpp
@@ -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)
+
+#include <boost/hana.hpp>
+
+#include <string>
+#include <type_traits>
+#include <utility>
+namespace hana = boost::hana;
+
+
+struct yes { std::string toString() const { return "yes"; } };
+struct no { };
+
+namespace has_toString_then {
+//! [has_toString.then]
+template <typename T, typename = void>
+struct has_toString
+ : std::false_type
+{ };
+
+template <typename T>
+struct has_toString<T, decltype((void)std::declval<T>().toString())>
+ : std::true_type
+{ };
+//! [has_toString.then]
+
+static_assert(has_toString<yes>::value, "");
+static_assert(!has_toString<no>::value, "");
+}
+
+//! [has_toString.now]
+auto has_toString = hana::is_valid([](auto&& obj) -> decltype(obj.toString()) { });
+//! [has_toString.now]
+
+BOOST_HANA_CONSTANT_CHECK(has_toString(yes{}));
+BOOST_HANA_CONSTANT_CHECK(hana::not_(has_toString(no{})));
+
+namespace optionalToString_then {
+//! [optionalToString.then]
+template <typename T>
+auto optionalToString(T const& obj)
+ -> std::enable_if_t<decltype(has_toString(obj))::value, std::string>
+{ return obj.toString(); }
+
+template <typename T>
+auto optionalToString(T const& obj)
+ -> std::enable_if_t<decltype(!has_toString(obj))::value, std::string>
+{ return "toString not defined"; }
+//! [optionalToString.then]
+
+// make sure they compile
+template std::string optionalToString(yes const&);
+template std::string optionalToString(no const&);
+}
+
+//! [optionalToString]
+template <typename T>
+std::string optionalToString(T const& obj) {
+ return hana::if_(has_toString(obj),
+ [](auto& x) { return x.toString(); },
+ [](auto& x) { return "toString not defined"; }
+ )(obj);
+}
+//! [optionalToString]
+
+
+int main() {
+BOOST_HANA_RUNTIME_CHECK(optionalToString(yes{}) == "yes");
+BOOST_HANA_RUNTIME_CHECK(optionalToString(no{}) == "toString not defined");
+
+
+{
+
+//! [non_static_member_from_object]
+auto has_member = hana::is_valid([](auto&& x) -> decltype((void)x.member) { });
+
+struct Foo { int member[4]; };
+struct Bar { };
+BOOST_HANA_CONSTANT_CHECK(has_member(Foo{}));
+BOOST_HANA_CONSTANT_CHECK(!has_member(Bar{}));
+//! [non_static_member_from_object]
+
+}{
+
+//! [non_static_member_from_type]
+auto has_member = hana::is_valid([](auto t) -> decltype(
+ (void)hana::traits::declval(t).member
+) { });
+
+struct Foo { int member[4]; };
+struct Bar { };
+BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
+BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
+//! [non_static_member_from_type]
+
+}{
+
+//! [nested_type_name]
+auto has_member = hana::is_valid([](auto t) -> hana::type<
+ typename decltype(t)::type::member
+//^^^^^^^^ needed because of the dependent context
+> { });
+
+struct Foo { struct member; /* not defined! */ };
+struct Bar { };
+BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
+BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
+//! [nested_type_name]
+
+}
+
+}
+
+namespace static_member {
+//! [static_member]
+auto has_member = hana::is_valid([](auto t) -> decltype(
+ (void)decltype(t)::type::member
+) { });
+
+struct Foo { static int member[4]; };
+struct Bar { };
+BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
+BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
+//! [static_member]
+}
+
+namespace nested_template {
+//! [nested_template]
+auto has_member = hana::is_valid([](auto t) -> decltype(hana::template_<
+ decltype(t)::type::template member
+ // ^^^^^^^^ needed because of the dependent context
+>) { });
+
+struct Foo { template <typename ...> struct member; };
+struct Bar { };
+BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
+BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
+//! [nested_template]
+}
+
+namespace template_specialization {
+//! [template_specialization]
+template <typename T, typename U>
+struct Foo;
+
+template <typename T>
+struct Bar;
+
+auto is_binary_template = hana::is_valid([](auto trait) -> decltype(
+ trait(hana::type_c<void>, hana::type_c<void>)
+) { });
+
+BOOST_HANA_CONSTANT_CHECK(is_binary_template(hana::template_<Foo>));
+BOOST_HANA_CONSTANT_CHECK(!is_binary_template(hana::template_<Bar>));
+//! [template_specialization]
+}
diff --git a/src/boost/libs/hana/example/tutorial/introspection.json.cpp b/src/boost/libs/hana/example/tutorial/introspection.json.cpp
new file mode 100644
index 000000000..d81dd001a
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introspection.json.cpp
@@ -0,0 +1,81 @@
+// 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.hpp>
+
+#include <iostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+namespace hana = boost::hana;
+using namespace std::literals;
+
+
+//! [utilities]
+template <typename Xs>
+std::string join(Xs&& xs, std::string sep) {
+ return hana::fold(hana::intersperse(std::forward<Xs>(xs), sep), "", hana::_ + hana::_);
+}
+
+std::string quote(std::string s) { return "\"" + s + "\""; }
+
+template <typename T>
+auto to_json(T const& x) -> decltype(std::to_string(x)) {
+ return std::to_string(x);
+}
+
+std::string to_json(char c) { return quote({c}); }
+std::string to_json(std::string s) { return quote(s); }
+//! [utilities]
+
+//! [Struct]
+template <typename T>
+ std::enable_if_t<hana::Struct<T>::value,
+std::string> to_json(T const& x) {
+ auto json = hana::transform(hana::keys(x), [&](auto name) {
+ auto const& member = hana::at_key(x, name);
+ return quote(hana::to<char const*>(name)) + " : " + to_json(member);
+ });
+
+ return "{" + join(std::move(json), ", ") + "}";
+}
+//! [Struct]
+
+//! [Sequence]
+template <typename Xs>
+ std::enable_if_t<hana::Sequence<Xs>::value,
+std::string> to_json(Xs const& xs) {
+ auto json = hana::transform(xs, [](auto const& x) {
+ return to_json(x);
+ });
+
+ return "[" + join(std::move(json), ", ") + "]";
+}
+//! [Sequence]
+
+
+int main() {
+//! [usage]
+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)
+ );
+};
+
+Car bmw{"BMW", "Z3"}, audi{"Audi", "A4"};
+Person john{"John", "Doe", 30};
+
+auto tuple = hana::make_tuple(john, audi, bmw);
+std::cout << to_json(tuple) << std::endl;
+//! [usage]
+}
diff --git a/src/boost/libs/hana/example/tutorial/introspection.sfinae.cpp b/src/boost/libs/hana/example/tutorial/introspection.sfinae.cpp
new file mode 100644
index 000000000..9b987ff9b
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/introspection.sfinae.cpp
@@ -0,0 +1,44 @@
+// 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.hpp>
+
+#include <string>
+#include <vector>
+namespace hana = boost::hana;
+
+
+struct yes { std::string toString() const { return "yes"; } };
+struct no { };
+
+//! [optionalToString.sfinae]
+template <typename T>
+std::string optionalToString(T const& obj) {
+ auto maybe_toString = hana::sfinae([](auto&& x) -> decltype(x.toString()) {
+ return x.toString();
+ });
+
+ return maybe_toString(obj).value_or("toString not defined");
+}
+//! [optionalToString.sfinae]
+
+int main() {
+BOOST_HANA_RUNTIME_CHECK(optionalToString(yes{}) == "yes");
+BOOST_HANA_RUNTIME_CHECK(optionalToString(no{}) == "toString not defined");
+
+{
+
+//! [maybe_add]
+auto maybe_add = hana::sfinae([](auto x, auto y) -> decltype(x + y) {
+ return x + y;
+});
+
+maybe_add(1, 2); // hana::just(3)
+
+std::vector<int> v;
+maybe_add(v, "foobar"); // hana::nothing
+//! [maybe_add]
+
+}
+}
diff --git a/src/boost/libs/hana/example/tutorial/mpl_cheatsheet.cpp b/src/boost/libs/hana/example/tutorial/mpl_cheatsheet.cpp
new file mode 100644
index 000000000..d9e87345a
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/mpl_cheatsheet.cpp
@@ -0,0 +1,58 @@
+// 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/config.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/ext/boost/mpl/vector.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <boost/mpl/fold.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <type_traits>
+namespace hana = boost::hana;
+namespace mpl = boost::mpl;
+
+
+namespace with_mpl {
+//! [mpl]
+using types = mpl::vector<long, float, short, float, long, long double>;
+using number_of_floats = mpl::fold<
+ types,
+ mpl::int_<0>,
+ mpl::if_<std::is_floating_point<mpl::_2>,
+ mpl::next<mpl::_1>,
+ mpl::_1
+ >
+>::type;
+static_assert(number_of_floats::value == 3, "");
+//! [mpl]
+}
+
+namespace with_hana {
+//! [hana]
+constexpr auto types = hana::tuple_t<long, float, short, float, long, long double>;
+BOOST_HANA_CONSTEXPR_LAMBDA auto number_of_floats = hana::fold_left(
+ types,
+ hana::int_c<0>,
+ [](auto count, auto t) {
+ return hana::if_(hana::trait<std::is_floating_point>(t),
+ count + hana::int_c<1>,
+ count
+ );
+ }
+);
+BOOST_HANA_CONSTANT_CHECK(number_of_floats == hana::int_c<3>);
+//! [hana]
+}
+
+int main() { }
diff --git a/src/boost/libs/hana/example/tutorial/quickstart.cpp b/src/boost/libs/hana/example/tutorial/quickstart.cpp
new file mode 100644
index 000000000..6358e503b
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/quickstart.cpp
@@ -0,0 +1,101 @@
+// 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)
+
+// Make sure `assert` always triggers an assertion
+#ifdef NDEBUG
+# undef NDEBUG
+#endif
+
+//! [additional_setup]
+#include <cassert>
+#include <iostream>
+#include <string>
+
+struct Fish { std::string name; };
+struct Cat { std::string name; };
+struct Dog { std::string name; };
+//! [additional_setup]
+
+//! [includes]
+#include <boost/hana.hpp>
+namespace hana = boost::hana;
+//! [includes]
+
+
+int main() {
+
+//! [animals]
+auto animals = hana::make_tuple(Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"});
+//! [animals]
+
+//! [algorithms]
+using namespace hana::literals;
+
+// Access tuple elements with operator[] instead of std::get.
+Cat garfield = animals[1_c];
+
+// Perform high level algorithms on tuples (this is like std::transform)
+auto names = hana::transform(animals, [](auto a) {
+ return a.name;
+});
+
+assert(hana::reverse(names) == hana::make_tuple("Snoopy", "Garfield", "Nemo"));
+//! [algorithms]
+
+
+//! [type-level]
+auto animal_types = hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Cat&>, hana::type_c<Dog>);
+
+auto no_pointers = hana::remove_if(animal_types, [](auto a) {
+ return hana::traits::is_pointer(a);
+});
+
+static_assert(no_pointers == hana::make_tuple(hana::type_c<Cat&>, hana::type_c<Dog>), "");
+//! [type-level]
+
+
+//! [has_name]
+auto has_name = hana::is_valid([](auto&& x) -> decltype((void)x.name) { });
+
+static_assert(has_name(garfield), "");
+static_assert(!has_name(1), "");
+//! [has_name]
+
+#if 0
+//! [screw_up]
+auto serialize = [](std::ostream& os, auto const& object) {
+ hana::for_each(os, [&](auto member) {
+ // ^^ oopsie daisy!
+ os << member << std::endl;
+ });
+};
+//! [screw_up]
+#endif
+
+//! [serialization]
+// 1. Give introspection capabilities to 'Person'
+struct Person {
+ BOOST_HANA_DEFINE_STRUCT(Person,
+ (std::string, name),
+ (int, age)
+ );
+};
+
+// 2. Write a generic serializer (bear with std::ostream for the example)
+auto serialize = [](std::ostream& os, auto const& object) {
+ hana::for_each(hana::members(object), [&](auto member) {
+ os << member << std::endl;
+ });
+};
+
+// 3. Use it
+Person john{"John", 30};
+serialize(std::cout, john);
+
+// output:
+// John
+// 30
+//! [serialization]
+
+}
diff --git a/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp b/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
new file mode 100644
index 000000000..4456aef32
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp
@@ -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)
+
+// Make sure `assert` always triggers an assertion
+#ifdef NDEBUG
+# undef NDEBUG
+#endif
+
+//! [full]
+#include <boost/hana.hpp>
+
+#include <boost/any.hpp>
+#include <cassert>
+#include <string>
+#include <typeindex>
+#include <typeinfo>
+#include <utility>
+namespace hana = boost::hana;
+
+//! [cases]
+template <typename T>
+auto case_ = [](auto f) {
+ return hana::make_pair(hana::type_c<T>, f);
+};
+
+struct default_t;
+auto default_ = case_<default_t>;
+//! [cases]
+
+//! [process]
+template <typename Any, typename Default>
+auto process(Any&, std::type_index const&, Default& default_) {
+ return default_();
+}
+
+template <typename Any, typename Default, typename Case, typename ...Rest>
+auto process(Any& a, std::type_index const& t, Default& default_,
+ Case& case_, Rest& ...rest)
+{
+ using T = typename decltype(+hana::first(case_))::type;
+ return t == typeid(T) ? hana::second(case_)(*boost::unsafe_any_cast<T>(&a))
+ : process(a, t, default_, rest...);
+}
+//! [process]
+
+//! [switch_]
+template <typename Any>
+auto switch_(Any& a) {
+ return [&a](auto ...cases_) {
+ auto cases = hana::make_tuple(cases_...);
+
+ auto default_ = hana::find_if(cases, [](auto const& c) {
+ return hana::first(c) == hana::type_c<default_t>;
+ });
+ static_assert(default_ != hana::nothing,
+ "switch is missing a default_ case");
+
+ auto rest = hana::filter(cases, [](auto const& c) {
+ return hana::first(c) != hana::type_c<default_t>;
+ });
+
+ return hana::unpack(rest, [&](auto& ...rest) {
+ return process(a, a.type(), hana::second(*default_), rest...);
+ });
+ };
+}
+//! [switch_]
+//! [full]
+
+
+int main() {
+using namespace std::literals;
+
+{
+
+//! [usage]
+boost::any a = 'x';
+std::string r = switch_(a)(
+ case_<int>([](auto i) { return "int: "s + std::to_string(i); }),
+ case_<char>([](auto c) { return "char: "s + std::string{c}; }),
+ default_([] { return "unknown"s; })
+);
+
+assert(r == "char: x"s);
+//! [usage]
+
+}{
+
+//! [result_inference]
+boost::any a = 'x';
+auto r = switch_(a)(
+ case_<int>([](auto) -> int { return 1; }),
+ case_<char>([](auto) -> long { return 2l; }),
+ default_([]() -> long long { return 3ll; })
+);
+
+// r is inferred to be a long long
+static_assert(std::is_same<decltype(r), long long>{}, "");
+assert(r == 2ll);
+//! [result_inference]
+
+}
+
+}
diff --git a/src/boost/libs/hana/example/tutorial/rationale.container.cpp b/src/boost/libs/hana/example/tutorial/rationale.container.cpp
new file mode 100644
index 000000000..9d419af15
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/rationale.container.cpp
@@ -0,0 +1,52 @@
+// 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.hpp>
+
+#include <boost/fusion/include/find_if.hpp>
+#include <boost/fusion/include/make_vector.hpp>
+#include <boost/mpl/quote.hpp>
+
+#include <type_traits>
+namespace fusion = boost::fusion;
+namespace mpl = boost::mpl;
+namespace hana = boost::hana;
+
+
+int main() {
+
+{
+
+//! [hana]
+auto tuple = hana::make_tuple(1, 'x', 3.4f);
+
+auto result = hana::find_if(tuple, [](auto const& x) {
+ return hana::traits::is_integral(hana::typeid_(x));
+});
+//! [hana]
+(void)result;
+
+#if 0
+//! [hana-explicit]
+some_type result = hana::find_if(tuple, [](auto const& x) {
+ return hana::traits::is_integral(hana::typeid_(x));
+});
+//! [hana-explicit]
+#endif
+
+}{
+
+//! [fusion]
+using Container = fusion::result_of::make_vector<int, char, float>::type;
+Container tuple = fusion::make_vector(1, 'x', 3.4f);
+
+using Predicate = mpl::quote1<std::is_integral>;
+using Result = fusion::result_of::find_if<Container, Predicate>::type;
+Result result = fusion::find_if<Predicate>(tuple);
+//! [fusion]
+(void)result;
+
+}
+
+}
diff --git a/src/boost/libs/hana/example/tutorial/tag_dispatching.cpp b/src/boost/libs/hana/example/tutorial/tag_dispatching.cpp
new file mode 100644
index 000000000..19ca9d156
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/tag_dispatching.cpp
@@ -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)
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <cstddef>
+#include <iostream>
+#include <sstream>
+namespace hana = boost::hana;
+
+
+//! [setup]
+template <typename Tag>
+struct print_impl {
+ template <typename X>
+ static void apply(std::ostream&, X const&) {
+ // possibly some default implementation
+ }
+};
+
+template <typename X>
+void print(std::ostream& os, X x) {
+ using Tag = typename hana::tag_of<X>::type;
+ print_impl<Tag>::apply(os, x);
+}
+//! [setup]
+
+//! [vector]
+struct vector_tag;
+
+struct vector0 {
+ using hana_tag = vector_tag;
+ static constexpr std::size_t size = 0;
+};
+
+template <typename T1>
+struct vector1 {
+ T1 t1;
+ using hana_tag = vector_tag;
+ static constexpr std::size_t size = 1;
+
+ template <typename Index>
+ auto const& operator[](Index i) const {
+ static_assert(i == 0u, "index out of bounds");
+ return t1;
+ }
+};
+
+template <typename T1, typename T2>
+struct vector2 {
+ T1 t1; T2 t2;
+ using hana_tag = vector_tag;
+ static constexpr std::size_t size = 2;
+
+ // Using Hana as a backend to simplify the example.
+ template <typename Index>
+ auto const& operator[](Index i) const {
+ return *hana::make_tuple(&t1, &t2)[i];
+ }
+};
+
+// and so on...
+//! [vector]
+
+//! [customize]
+template <>
+struct print_impl<vector_tag> {
+ template <typename vectorN>
+ static void apply(std::ostream& os, vectorN xs) {
+ auto N = hana::size_c<vectorN::size>;
+
+ os << "[";
+ N.times.with_index([&](auto i) {
+ os << xs[i];
+ if (i != N - hana::size_c<1>) os << ", ";
+ });
+ os << "]";
+ }
+};
+//! [customize]
+
+#if 0
+//! [customize-when]
+template <typename Tag>
+struct print_impl<Tag, hana::when<Tag represents some kind of sequence>> {
+ template <typename Seq>
+ static void apply(std::ostream& os, Seq xs) {
+ // Some implementation for any sequence
+ }
+};
+//! [customize-when]
+#endif
+
+int main() {
+ {
+ std::stringstream ss;
+ vector0 v0;
+ print(ss, v0);
+ BOOST_HANA_RUNTIME_CHECK(ss.str() == "[]");
+ }
+
+ {
+ std::stringstream ss;
+ vector1<int> v1{1};
+ print(ss, v1);
+ BOOST_HANA_RUNTIME_CHECK(ss.str() == "[1]");
+ }
+
+ {
+ std::stringstream ss;
+ vector2<int, char> v2{1, 'x'};
+ print(ss, v2);
+ BOOST_HANA_RUNTIME_CHECK(ss.str() == "[1, x]");
+ }
+}
+
+namespace old_way {
+//! [old_way]
+void print(std::ostream& os, vector0)
+{ os << "[]"; }
+
+template <typename T1>
+void print(std::ostream& os, vector1<T1> v)
+{ os << "[" << v.t1 << "]"; }
+
+template <typename T1, typename T2>
+void print(std::ostream& os, vector2<T1, T2> v)
+{ os << "[" << v.t1 << ", " << v.t2 << "]"; }
+
+// and so on...
+//! [old_way]
+}
+
+namespace preconditions {
+//! [preconditions]
+template <typename X>
+void print(std::ostream& os, X x) {
+ // **** check some precondition ****
+
+ // The precondition only has to be checked here; implementations
+ // can assume their arguments to always be sane.
+
+ using Tag = typename hana::tag_of<X>::type;
+ print_impl<Tag>::apply(os, x);
+}
+//! [preconditions]
+}
+
+namespace function_objects {
+//! [function_objects]
+// Defining a function object is only needed once and implementations do not
+// have to worry about static initialization and other painful tricks.
+struct print_t {
+ template <typename X>
+ void operator()(std::ostream& os, X x) const {
+ using Tag = typename hana::tag_of<X>::type;
+ print_impl<Tag>::apply(os, x);
+ }
+};
+constexpr print_t print{};
+//! [function_objects]
+
+static_assert(sizeof(print) || true, "remove unused variable print warning");
+}
diff --git a/src/boost/libs/hana/example/tutorial/type.cpp b/src/boost/libs/hana/example/tutorial/type.cpp
new file mode 100644
index 000000000..92010d499
--- /dev/null
+++ b/src/boost/libs/hana/example/tutorial/type.cpp
@@ -0,0 +1,260 @@
+// 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.hpp>
+#include <boost/hana/ext/std/integral_constant.hpp>
+
+#include <boost/mpl/copy_if.hpp>
+#include <boost/mpl/equal.hpp>
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/min_element.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/sizeof.hpp>
+#include <boost/mpl/vector.hpp>
+
+#include <boost/fusion/include/at_key.hpp>
+#include <boost/fusion/include/equal_to.hpp>
+#include <boost/fusion/include/filter_if.hpp>
+#include <boost/fusion/include/make_map.hpp>
+#include <boost/fusion/include/make_vector.hpp>
+
+#include <string>
+#include <type_traits>
+#include <vector>
+namespace fusion = boost::fusion;
+namespace mpl = boost::mpl;
+namespace hana = boost::hana;
+using namespace hana::literals;
+
+
+template <int n>
+struct storage { char weight[n]; };
+
+int main() {
+
+{
+
+//! [tuple]
+auto types = hana::make_tuple(hana::type_c<int*>, hana::type_c<char&>, hana::type_c<void>);
+auto char_ref = types[1_c];
+
+BOOST_HANA_CONSTANT_CHECK(char_ref == hana::type_c<char&>);
+//! [tuple]
+
+}{
+
+//! [filter.MPL]
+using types = mpl::vector<int, char&, void*>;
+using ts = mpl::copy_if<types, mpl::or_<std::is_pointer<mpl::_1>,
+ std::is_reference<mpl::_1>>>::type;
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// placeholder expression
+
+static_assert(mpl::equal<ts, mpl::vector<char&, void*>>::value, "");
+//! [filter.MPL]
+
+}{
+
+using hana::traits::is_pointer; // the traits namespace was not introduced
+using hana::traits::is_reference; // yet, so we use unqualified names for now
+
+//! [filter.Hana]
+auto types = hana::tuple_t<int*, char&, void>;
+
+auto ts = hana::filter(types, [](auto t) {
+ return is_pointer(t) || is_reference(t);
+});
+
+BOOST_HANA_CONSTANT_CHECK(ts == hana::tuple_t<int*, char&>);
+//! [filter.Hana]
+
+}{
+
+//! [single_library.then]
+// types (MPL)
+using types = mpl::vector<int*, char&, void>;
+using ts = mpl::copy_if<types, mpl::or_<std::is_pointer<mpl::_1>,
+ std::is_reference<mpl::_1>>>::type;
+
+// values (Fusion)
+auto values = fusion::make_vector(1, 'c', nullptr, 3.5);
+auto vs = fusion::filter_if<std::is_integral<mpl::_1>>(values);
+//! [single_library.then]
+
+static_assert(mpl::equal<ts, mpl::vector<int*, char&>>::value, "");
+BOOST_HANA_RUNTIME_CHECK(vs == fusion::make_vector(1, 'c'));
+
+}{
+
+using hana::traits::is_pointer;
+using hana::traits::is_reference;
+using hana::traits::is_integral;
+
+//! [single_library.Hana]
+// types
+auto types = hana::tuple_t<int*, char&, void>;
+auto ts = hana::filter(types, [](auto t) {
+ return is_pointer(t) || is_reference(t);
+});
+
+// values
+auto values = hana::make_tuple(1, 'c', nullptr, 3.5);
+auto vs = hana::filter(values, [](auto const& t) {
+ return is_integral(hana::typeid_(t));
+});
+//! [single_library.Hana]
+
+BOOST_HANA_CONSTANT_CHECK(ts == hana::tuple_t<int*, char&>);
+BOOST_HANA_RUNTIME_CHECK(vs == hana::make_tuple(1, 'c'));
+
+}{
+
+//! [make_map.Fusion]
+auto map = fusion::make_map<char, int, long, float, double, void>(
+ "char", "int", "long", "float", "double", "void"
+);
+
+std::string Int = fusion::at_key<int>(map);
+BOOST_HANA_RUNTIME_CHECK(Int == "int");
+//! [make_map.Fusion]
+
+}{
+
+//! [make_map.Hana]
+auto map = hana::make_map(
+ hana::make_pair(hana::type_c<char>, "char"),
+ hana::make_pair(hana::type_c<int>, "int"),
+ hana::make_pair(hana::type_c<long>, "long"),
+ hana::make_pair(hana::type_c<float>, "float"),
+ hana::make_pair(hana::type_c<double>, "double")
+);
+
+std::string Int = map[hana::type_c<int>];
+BOOST_HANA_RUNTIME_CHECK(Int == "int");
+//! [make_map.Hana]
+
+}{
+
+using hana::traits::add_pointer;
+
+//! [skip_first_step]
+auto types = hana::tuple_t<int*, char&, void>; // first step skipped
+
+auto pointers = hana::transform(types, [](auto t) {
+ return add_pointer(t);
+});
+//! [skip_first_step]
+
+BOOST_HANA_CONSTANT_CHECK(pointers == hana::tuple_t<int**, char*, void*>);
+
+}{
+
+//! [traits]
+BOOST_HANA_CONSTANT_CHECK(hana::traits::add_pointer(hana::type_c<int>) == hana::type_c<int*>);
+BOOST_HANA_CONSTANT_CHECK(hana::traits::common_type(hana::type_c<int>, hana::type_c<long>) == hana::type_c<long>);
+BOOST_HANA_CONSTANT_CHECK(hana::traits::is_integral(hana::type_c<int>));
+
+auto types = hana::tuple_t<int, char, long>;
+BOOST_HANA_CONSTANT_CHECK(hana::all_of(types, hana::traits::is_integral));
+//! [traits]
+
+}{
+
+//! [extent]
+auto extent = [](auto t, auto n) {
+ return std::extent<typename decltype(t)::type, hana::value(n)>{};
+};
+
+BOOST_HANA_CONSTANT_CHECK(extent(hana::type_c<char>, hana::int_c<1>) == hana::size_c<0>);
+BOOST_HANA_CONSTANT_CHECK(extent(hana::type_c<char[1][2]>, hana::int_c<1>) == hana::size_c<2>);
+//! [extent]
+
+}
+
+}
+
+namespace mpl_based {
+//! [smallest.MPL]
+template <typename ...T>
+struct smallest
+ : mpl::deref<
+ typename mpl::min_element<
+ mpl::vector<T...>,
+ mpl::less<mpl::sizeof_<mpl::_1>, mpl::sizeof_<mpl::_2>>
+ >::type
+ >
+{ };
+
+template <typename ...T>
+using smallest_t = typename smallest<T...>::type;
+
+static_assert(std::is_same<
+ smallest_t<char, long, long double>,
+ char
+>::value, "");
+//! [smallest.MPL]
+
+static_assert(std::is_same<
+ smallest_t<storage<3>, storage<1>, storage<2>>,
+ storage<1>
+>::value, "");
+} // end namespace mpl_based
+
+namespace hana_based {
+//! [smallest.Hana]
+template <typename ...T>
+auto smallest = hana::minimum(hana::make_tuple(hana::type_c<T>...), [](auto t, auto u) {
+ return hana::sizeof_(t) < hana::sizeof_(u);
+});
+
+template <typename ...T>
+using smallest_t = typename decltype(smallest<T...>)::type;
+
+static_assert(std::is_same<
+ smallest_t<char, long, long double>, char
+>::value, "");
+//! [smallest.Hana]
+
+static_assert(std::is_same<
+ smallest_t<storage<3>, storage<1>, storage<2>>,
+ storage<1>
+>::value, "");
+} // end namespace hana_based
+
+
+namespace metafunction1 {
+//! [metafunction1]
+template <template <typename> class F, typename T>
+constexpr auto metafunction(hana::basic_type<T> const&)
+{ return hana::type_c<typename F<T>::type>; }
+
+auto t = hana::type_c<int>;
+BOOST_HANA_CONSTANT_CHECK(metafunction<std::add_pointer>(t) == hana::type_c<int*>);
+//! [metafunction1]
+}
+
+namespace metafunction2 {
+//! [metafunction2]
+template <template <typename ...> class F, typename ...T>
+constexpr auto metafunction(hana::basic_type<T> const& ...)
+{ return hana::type_c<typename F<T...>::type>; }
+
+BOOST_HANA_CONSTANT_CHECK(
+ metafunction<std::common_type>(hana::type_c<int>, hana::type_c<long>) == hana::type_c<long>
+);
+//! [metafunction2]
+}
+
+namespace _template {
+//! [template_]
+template <template <typename ...> class F, typename ...T>
+constexpr auto template_(hana::basic_type<T> const& ...)
+{ return hana::type_c<F<T...>>; }
+
+BOOST_HANA_CONSTANT_CHECK(
+ template_<std::vector>(hana::type_c<int>) == hana::type_c<std::vector<int>>
+);
+//! [template_]
+}