From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- .../libs/hana/example/tutorial/algorithms.cpp | 148 +++++ .../libs/hana/example/tutorial/appendix_mpl.cpp | 697 +++++++++++++++++++++ src/boost/libs/hana/example/tutorial/concepts.cpp | 64 ++ .../example/tutorial/constant_side_effects.cpp | 36 ++ .../libs/hana/example/tutorial/containers.cpp | 106 ++++ .../hana/example/tutorial/ext/fusion_to_hana.cpp | 31 + .../libs/hana/example/tutorial/ext/mpl_vector.cpp | 40 ++ .../libs/hana/example/tutorial/ext/ratio_plus.cpp | 15 + .../libs/hana/example/tutorial/include_ext.cpp | 16 + .../hana/example/tutorial/integral-branching.cpp | 55 ++ src/boost/libs/hana/example/tutorial/integral.cpp | 128 ++++ .../libs/hana/example/tutorial/introduction.cpp | 80 +++ .../hana/example/tutorial/introspection.adapt.cpp | 100 +++ .../libs/hana/example/tutorial/introspection.cpp | 158 +++++ .../hana/example/tutorial/introspection.json.cpp | 81 +++ .../hana/example/tutorial/introspection.sfinae.cpp | 44 ++ .../libs/hana/example/tutorial/mpl_cheatsheet.cpp | 58 ++ .../libs/hana/example/tutorial/quickstart.cpp | 101 +++ .../hana/example/tutorial/quickstart.switchAny.cpp | 105 ++++ .../hana/example/tutorial/rationale.container.cpp | 52 ++ .../libs/hana/example/tutorial/tag_dispatching.cpp | 170 +++++ src/boost/libs/hana/example/tutorial/type.cpp | 260 ++++++++ 22 files changed, 2545 insertions(+) create mode 100644 src/boost/libs/hana/example/tutorial/algorithms.cpp create mode 100644 src/boost/libs/hana/example/tutorial/appendix_mpl.cpp create mode 100644 src/boost/libs/hana/example/tutorial/concepts.cpp create mode 100644 src/boost/libs/hana/example/tutorial/constant_side_effects.cpp create mode 100644 src/boost/libs/hana/example/tutorial/containers.cpp create mode 100644 src/boost/libs/hana/example/tutorial/ext/fusion_to_hana.cpp create mode 100644 src/boost/libs/hana/example/tutorial/ext/mpl_vector.cpp create mode 100644 src/boost/libs/hana/example/tutorial/ext/ratio_plus.cpp create mode 100644 src/boost/libs/hana/example/tutorial/include_ext.cpp create mode 100644 src/boost/libs/hana/example/tutorial/integral-branching.cpp create mode 100644 src/boost/libs/hana/example/tutorial/integral.cpp create mode 100644 src/boost/libs/hana/example/tutorial/introduction.cpp create mode 100644 src/boost/libs/hana/example/tutorial/introspection.adapt.cpp create mode 100644 src/boost/libs/hana/example/tutorial/introspection.cpp create mode 100644 src/boost/libs/hana/example/tutorial/introspection.json.cpp create mode 100644 src/boost/libs/hana/example/tutorial/introspection.sfinae.cpp create mode 100644 src/boost/libs/hana/example/tutorial/mpl_cheatsheet.cpp create mode 100644 src/boost/libs/hana/example/tutorial/quickstart.cpp create mode 100644 src/boost/libs/hana/example/tutorial/quickstart.switchAny.cpp create mode 100644 src/boost/libs/hana/example/tutorial/rationale.container.cpp create mode 100644 src/boost/libs/hana/example/tutorial/tag_dispatching.cpp create mode 100644 src/boost/libs/hana/example/tutorial/type.cpp (limited to 'src/boost/libs/hana/example/tutorial') 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 +#include + +#include +#include +#include +#include +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{}; +}); + +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{}; }; + +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{}; +}); + +BOOST_HANA_CONSTANT_CHECK(any_cat); +//! [cross_phase.any_of_compile_time] + +}{ + +//! [cross_phase.any_of_explicit] +hana::integral_constant any_cat = hana::any_of(animals, [](auto x) { + return std::is_same{}; +}); + +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 != hana::type_c; +}); +//! [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 xs{1, '2', std::string{"345"}}; +static_assert(std::tuple_size::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 +#include +#include + +#include +#include +#include + +#include +#include +namespace hana = boost::hana; +namespace mpl = boost::mpl; + + +namespace hpl { +////////////////////////////////////////////////////////////////////////////// +// Utilities +////////////////////////////////////////////////////////////////////////////// +namespace detail { + template + constexpr auto mpl_predicate = hana::integral(hana::metafunction_class< + typename mpl::lambda::type + >); + + template + constexpr auto mpl_metafunction = hana::metafunction_class< + typename mpl::lambda::type + >; +} + +////////////////////////////////////////////////////////////////////////////// +// integral_c +////////////////////////////////////////////////////////////////////////////// +template +using integral_c = std::integral_constant; + +template +using int_ = integral_c; + +template +using long_ = integral_c; + +template +using bool_ = integral_c; + +using true_ = bool_; +using false_ = bool_; + + +////////////////////////////////////////////////////////////////////////////// +// Sequences, compile-time integers & al +// +// Differences with the MPL: +// 1. `pair<...>::first` and `pair<...>::second` won't work; +// use `first>` instead +////////////////////////////////////////////////////////////////////////////// +template +using vector = hana::tuple...>; + +template +using vector_c = hana::tuple...>; + +template +using range_c = decltype(hana::range_c); + + +template +using pair = hana::pair, hana::type>; + +template +struct first : decltype(+hana::first(P{})) { }; + +template +struct second : decltype(+hana::second(P{})) { }; + + +////////////////////////////////////////////////////////////////////////////// +// Miscellaneous metafunctions +////////////////////////////////////////////////////////////////////////////// +template +struct equal_to + : bool_ +{ }; + +template +struct less + : bool_<(C1::value < C2::value)> +{ }; + +template +struct greater + : bool_<(C1::value > C2::value)> +{ }; + +template +struct next + : integral_c +{ }; + +////////////////////////////////////////////////////////////////////////////// +// 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 +struct at + : decltype(hana::at(Sequence{}, N{})) +{ }; + +template +using at_c = at>; + +template +struct back + : decltype(+hana::back(Sequence{})) +{ }; + +template +struct empty + : decltype(hana::is_empty(Sequence{})) +{ }; + +template +struct front + : decltype(+hana::front(Sequence{})) +{ }; + +template +struct pop_back { + using type = decltype(hana::drop_back( + hana::to_tuple(Sequence{}), hana::size_c<1> + )); +}; + +template +struct pop_front { + using type = decltype(hana::drop_front(Sequence{})); +}; + +template +struct push_back { + using type = decltype(hana::append(Sequence{}, hana::type_c)); +}; + +template +struct push_front { + using type = decltype(hana::prepend(Sequence{}, hana::type_c)); +}; + +template +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 +struct fold + : decltype(hana::fold( + Sequence{}, hana::type_c, detail::mpl_metafunction + )) +{ }; + +template +struct reverse_fold + : decltype(hana::reverse_fold( + Sequence{}, hana::type_c, detail::mpl_metafunction + )) +{ }; + +template +using accumulate = fold; + +////////////////////////////////////////////////////////////////////////////// +// 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 +struct find_if + : decltype(hana::find_if(Sequence{}, detail::mpl_predicate)) +{ }; + +template +struct find + : decltype(hana::find(Sequence{}, hana::type_c)) +{ }; + +template +struct contains + : decltype(hana::contains(Sequence{}, hana::type_c)) +{ }; + +template +struct count + : decltype(hana::count(Sequence{}, hana::type_c)) +{ }; + +template +struct count_if + : decltype(hana::count_if(Sequence{}, detail::mpl_predicate)) +{ }; + +template > +struct min_element + : decltype(hana::minimum(Sequence{}, detail::mpl_predicate)) +{ }; + +template > +struct max_element + : decltype(hana::maximum(Sequence{}, detail::mpl_predicate)) +{ }; + +template > +struct equal + : decltype( // inefficient but whatever + hana::length(S1{}) == hana::length(S2{}) && + hana::all(hana::zip_shortest_with(detail::mpl_predicate, + 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 +struct copy { + using type = decltype(hana::to_tuple(Sequence{})); +}; + +template +struct copy_if { + using type = decltype(hana::filter( + hana::to_tuple(Sequence{}), + detail::mpl_predicate + )); +}; + +template +struct transform; + +template +struct transform { + using type = decltype(hana::transform( + hana::to_tuple(Sequence{}), detail::mpl_metafunction + )); +}; + +template +struct transform { + using type = decltype(hana::zip_with( + detail::mpl_metafunction, + hana::to_tuple(S1{}), + hana::to_tuple(S2{}) + )); +}; + +template +struct replace { + using type = decltype(hana::replace( + hana::to_tuple(Sequence{}), + hana::type_c, + hana::type_c + )); +}; + +template +struct replace_if { + using type = decltype(hana::replace_if( + hana::to_tuple(Sequence{}), + detail::mpl_predicate, + hana::type_c + )); +}; + +template +struct remove { + using type = decltype(hana::filter( + hana::to_tuple(Sequence{}), + hana::not_equal.to(hana::type_c) + )); +}; + +template +struct remove_if { + using type = decltype(hana::filter( + hana::to_tuple(Sequence{}), + hana::compose(hana::not_, detail::mpl_predicate) + )); +}; + +template +struct unique { + using type = decltype(hana::unique( + hana::to_tuple(Sequence{}), + detail::mpl_predicate + )); +}; + +template +struct partition { + using hana_pair = decltype(hana::partition( + hana::to_tuple(Sequence{}), + detail::mpl_predicate + )); + using type = pair< + decltype(hana::first(hana_pair{})), + decltype(hana::second(hana_pair{})) + >; +}; + +template > +struct sort { + using type = decltype(hana::sort( + hana::to_tuple(Sequence{}), detail::mpl_predicate + )); +}; + +template +struct reverse { + using type = decltype(hana::reverse(hana::to_tuple(Sequence{}))); +}; + + +////////////////////////////////////////////////////////////////////////////// +// Runtime algorithms +////////////////////////////////////////////////////////////////////////////// +template +void for_each(F f) { + hana::for_each(Sequence{}, [&f](auto t) { + f(typename decltype(t)::type{}); + }); +} + +template +void for_each(F f) { + for_each::type>(f); +} + +} // end namespace hpl + + +template +struct is_odd + : hpl::bool_<(N::value % 2)> +{ }; + + +int main() { +using namespace hpl; + +////////////////////////////////////////////////////////////////////////////// +// Misc +////////////////////////////////////////////////////////////////////////////// + +// pair +{ + static_assert(std::is_same>::type, int>{}, ""); + static_assert(std::is_same>::type, float>{}, ""); +} + +////////////////////////////////////////////////////////////////////////////// +// Intrinsics +////////////////////////////////////////////////////////////////////////////// + +// at +{ + using range = range_c; + static_assert(at>::value == 10, ""); + static_assert(at>::value == 20, ""); + static_assert(at>::value == 50, ""); +} + +// at_c +{ + using range = range_c; + static_assert(at_c::value == 10, ""); + static_assert(at_c::value == 20, ""); + static_assert(at_c::value == 50, ""); +} + +// back +{ + using range1 = range_c; + using range2 = range_c; + using range3 = range_c; + using types = vector; + static_assert(back::value == 0, ""); + static_assert(back::value == 9, ""); + static_assert(back::value == -1, ""); + static_assert(std::is_same::type, float>{}, ""); +} + +// empty +{ + using empty_range = range_c; + using types = vector; + static_assert(empty{}, ""); + static_assert(!empty{}, ""); +} + +// front +{ + using types1 = vector; + using types2 = vector; + using types3 = vector; + static_assert(std::is_same::type, long>{}, ""); + static_assert(std::is_same::type, int>{}, ""); + static_assert(std::is_same::type, char>{}, ""); +} + +// pop_back +{ + using types1 = vector; + using types2 = vector; + using types3 = vector; + + + using result1 = pop_back::type; + using result2 = pop_back::type; + using result3 = pop_back::type; + + static_assert(size::value == 0, ""); + static_assert(size::value == 1, ""); + static_assert(size::value == 2, ""); + + static_assert(std::is_same< back::type, long>{}, ""); + static_assert(std::is_same< back::type, int>{}, ""); +} + +// pop_front +{ + using types1 = vector; + using types2 = vector; + using types3 = vector; + + using result1 = pop_front::type; + using result2 = pop_front::type; + using result3 = pop_front::type; + + static_assert(size::value == 0, ""); + static_assert(size::value == 1, ""); + static_assert(size::value == 2, ""); + + static_assert(std::is_same::type, long>{}, ""); + static_assert(std::is_same::type, int>{}, ""); +} + +// push_back +{ + using bools = vector_c; + using message = push_back::type; + static_assert(back::type::value == false, ""); + static_assert(count_if>{} == 6u, ""); +} + +// push_front +{ + using v = vector_c; + static_assert(size{} == 7u, ""); + + using fibonacci = push_front>::type; + static_assert(size{} == 8u, ""); + + static_assert(equal< + fibonacci, + vector_c, + equal_to + >{}, ""); +} + +// size +{ + using empty_list = vector<>; + using numbers = vector_c; + using more_numbers = range_c; + + static_assert(size{} == 0u, ""); + static_assert(size{} == 6u, ""); + static_assert(size{} == 100u, ""); +} + + +////////////////////////////////////////////////////////////////////////////// +// Iteration algorithms +////////////////////////////////////////////////////////////////////////////// + +// fold +{ + using types = vector; + using number_of_floats = fold, + mpl::if_, + next, + mpl::_1 + > + >::type; + static_assert(number_of_floats{} == 4, ""); +} + +// reverse_fold +{ + using numbers = vector_c; + using negatives = vector_c; + using result = reverse_fold, + mpl::if_>, + push_front, + mpl::_1 + > + >::type; + static_assert(equal{}, ""); +} + +////////////////////////////////////////////////////////////////////////////// +// Query algorithms +////////////////////////////////////////////////////////////////////////////// + +// find_if +{ + using types = vector; + using found = find_if>::type; + static_assert(std::is_same{}, ""); +} + +// find +{ + using types = vector; + static_assert(std::is_same::type, unsigned>{}, ""); +} + +// contains +{ + using types = vector; + static_assert(!contains{}, ""); +} + +// count +{ + using types = vector; + static_assert(count{} == 2u, ""); +} + +// count_if +{ + using types = vector; + static_assert(count_if>{} == 1u, ""); + static_assert(count_if>{} == 2u, ""); + static_assert(count_if>{} == 0u, ""); +} + +// min_element (MPL's example is completely broken) +{ +} + +// max_element (MPL's example is completely broken) +{ +} + +// equal +{ + using s1 = vector; + using s2 = vector; + static_assert(!equal{}, ""); +} + + +////////////////////////////////////////////////////////////////////////////// +// Transformaton algorithms +////////////////////////////////////////////////////////////////////////////// +// copy +{ + using numbers = vector_c; + using result = copy>::type; + static_assert(size{} == 10u, ""); + static_assert(equal>{}, ""); +} + +// copy_if +{ + using result = copy_if, less>>::type; + static_assert(size{} == 5u, ""); + static_assert(equal>{}, ""); +} + +// transform +{ + using types = vector; + using pointers = vector; + using result = transform>::type; + static_assert(equal{}, ""); +} + +// replace +{ + using types = vector; + using expected = vector; + using result = replace< types,float,double >::type; + static_assert(equal{}, ""); +} + +// replace_if +{ + using numbers = vector_c; + using expected = vector_c; + using result = replace_if>, int_<0>>::type; + static_assert(equal>{}, ""); +} + +// remove +{ + using types = vector; + using result = hpl::remove::type; + static_assert(equal>{}, ""); +} + +// remove_if +{ + using numbers = vector_c; + using result = remove_if > >::type; + static_assert(equal, mpl::quote2>{}, ""); +} + +// unique +{ + using types = vector; + using expected = vector; + using result = unique>::type; + static_assert(equal{}, ""); +} + +// partition +{ + using r = partition, is_odd>::type; + static_assert(equal::type, vector_c>{}, ""); + static_assert(equal::type, vector_c>{}, ""); +} + +// sort +{ + using numbers = vector_c; + using expected = vector_c; + using result = sort::type; + static_assert(equal>{}, ""); +} + +// reverse +{ + using numbers = vector_c; + using result = reverse::type; + static_assert(equal>{}, ""); +} + +////////////////////////////////////////////////////////////////////////////// +// Runtime algorithms +////////////////////////////////////////////////////////////////////////////// + +// for_each +{ + auto value_printer = [](auto x) { + std::cout << x << '\n'; + }; + + for_each >(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 +#include +#include + +#include +#include +namespace hana = boost::hana; + + +namespace with_special_base_class { +//! [special_base_class] +struct special_base_class { }; + +template +struct print_impl : special_base_class { + template + static constexpr auto apply(Args&& ...) = delete; +}; + +template +struct Printable + : hana::integral_constant>>::value + > +{ }; +//! [special_base_class] + +//! [special_base_class_customize] +struct Person { std::string name; }; + +template <> +struct print_impl /* don't inherit from special_base_class */ { + // ... implementation ... +}; + +static_assert(Printable::value, ""); +static_assert(!Printable::value, ""); +//! [special_base_class_customize] +} + +namespace actual { +//! [actual] +template +struct print_impl : hana::default_ { + template + static constexpr auto apply(Args&& ...) = delete; +}; + +template +struct Printable + : hana::integral_constant>>::value + > +{ }; +//! [actual] + +static_assert(!Printable::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 + +#include +namespace hana = boost::hana; + + +namespace pure { +//! [pure] +template +auto identity(X x) { return x; } + +auto x = identity(hana::bool_c); +static_assert(hana::value(x), ""); +//! [pure] +} + +namespace impure { +//! [impure_identity] +template +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); +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 + +#include +#include +#include +#include +#include +namespace hana = boost::hana; +using namespace hana::literals; +using namespace std::literals; + + +int main() { + +{ + +//! [make] +auto xs = hana::make(1, 2.2, 'a', "bcde"s); +//! [make] + +}{ + +//! [make] +constexpr auto r = hana::make(hana::int_c<3>, hana::int_c<10>); +static_assert(r == hana::make_range(hana::int_c<3>, hana::int_c<10>), ""); +//! [make] + +}{ + +//! [tuple_constructor] +hana::tuple 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 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 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 ints = { /* huge vector of ints */ }; +std::vector strings = { /* huge vector of strings */ }; + +auto map = hana::make_map( + hana::make_pair(hana::type_c, std::ref(ints)), + hana::make_pair(hana::type_c, std::ref(strings)) +); + +auto& v = map[hana::type_c].get(); +BOOST_HANA_RUNTIME_CHECK(&v == &ints); +//! [reference_wrapper] + +} + +} + + +namespace overloading { +//! [overloading] +template +void f(std::vector xs) { + // ... +} + +template ()>> +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 +#include +#include + +#include + +#include +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 +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 +#include +#include +#include + +#include +#include +namespace hana = boost::hana; +namespace mpl = boost::mpl; + + +//! [front] +#include // bridge header + +using Vector = mpl::vector; +static_assert(hana::front(Vector{}) == hana::type_c, ""); +//! [front] + + +namespace _ns0 { +//! [size] +using Size = mpl::size::type; +static_assert(hana::equal(Size{}, hana::int_c<3>), ""); // breaks! +//! [size] +} + + +//! [size-fixed] +#include + +using Size = mpl::size::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 +#include + +#include +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 +#include +#include // still required to create a tuple +namespace hana = boost::hana; + + +int main() { + constexpr std::tuple 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 +#include + +#include +#include +#include +#include +namespace hana = boost::hana; + + + +namespace ns1 { +//! [make_unique.if_] +template +std::unique_ptr make_unique(Args&&... args) { + return hana::if_(std::is_constructible{}, + [](auto&& ...x) { return std::unique_ptr(new T(std::forward(x)...)); }, + [](auto&& ...x) { return std::unique_ptr(new T{std::forward(x)...}); } + )(std::forward(args)...); +} +//! [make_unique.if_] +} + + +namespace ns2 { +//! [make_unique.eval_if] +template +std::unique_ptr make_unique(Args&&... args) { + return hana::eval_if(std::is_constructible{}, + [&](auto _) { return std::unique_ptr(new T(std::forward(_(args))...)); }, + [&](auto _) { return std::unique_ptr(new T{std::forward(_(args))...}); } + ); +} +//! [make_unique.eval_if] +} + +struct Student { + std::string name; + int age; +}; + +int main() { + { + std::unique_ptr a = ns1::make_unique(3); + std::unique_ptr b = ns1::make_unique("Bob", 25); + } + { + std::unique_ptr a = ns2::make_unique(3); + std::unique_ptr b = ns2::make_unique("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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +namespace hana = boost::hana; + + +namespace support { +template ::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 ::value +>> +constexpr auto sqrt(T const&) { + return hana::integral_c; +} +} // end namespace support + + +namespace then { +namespace mpl = boost::mpl; + +template +struct sqrt + : mpl::integral_c +{ }; + +template +struct point { + using x = X; + using y = Y; +}; + +//! [distance-mpl] +template +struct distance { + using xs = typename mpl::minus::type; + using ys = typename mpl::minus::type; + using type = typename sqrt< + typename mpl::plus< + typename mpl::multiplies::type, + typename mpl::multiplies::type + >::type + >::type; +}; + +static_assert(mpl::equal_to< + distance, mpl::int_<5>>, + point, mpl::int_<2>>>::type, + mpl::int_<5> +>::value, ""); +//! [distance-mpl] +} + + +namespace now { +namespace hana = boost::hana; +using namespace hana::literals; + +template +struct _point { + X x; + Y y; +}; +template +constexpr _point point(X x, Y y) { return {x, y}; } + +using support::sqrt; // avoid conflicts with ::sqrt + +//! [distance-hana] +template +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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +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 ints{1, 2, 3, 4}; +std::vector strings; +std::transform(ints.begin(), ints.end(), std::back_inserter(strings), f); + +assert((strings == std::vector{"1", "4", "9", "16"})); +//! [runtime] + +}{ + +//! [heterogeneous] +auto to_string = [](auto t) { + std::stringstream ss; + ss << t; + return ss.str(); +}; + +fusion::vector seq{1, "abc", 3.4f}; +fusion::vector + strings = fusion::transform(seq, to_string); + +assert(strings == fusion::make_vector("1"s, "abc"s, "3.4"s)); +//! [heterogeneous] + +} + +} + +//! [type-level] +template +struct add_const_pointer { + using type = T const*; +}; + +using types = mpl::vector; +using pointers = mpl::transform>::type; + +static_assert(mpl::equal< + pointers, + mpl::vector +>::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 + +#include +#include +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(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(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] +auto map = hana::insert(hana::to(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] + +} + +#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 + +#include +#include +#include +namespace hana = boost::hana; + + +struct yes { std::string toString() const { return "yes"; } }; +struct no { }; + +namespace has_toString_then { +//! [has_toString.then] +template +struct has_toString + : std::false_type +{ }; + +template +struct has_toString().toString())> + : std::true_type +{ }; +//! [has_toString.then] + +static_assert(has_toString::value, ""); +static_assert(!has_toString::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 +auto optionalToString(T const& obj) + -> std::enable_if_t +{ return obj.toString(); } + +template +auto optionalToString(T const& obj) + -> std::enable_if_t +{ return "toString not defined"; } +//! [optionalToString.then] + +// make sure they compile +template std::string optionalToString(yes const&); +template std::string optionalToString(no const&); +} + +//! [optionalToString] +template +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)); +BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c)); +//! [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)); +BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c)); +//! [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)); +BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c)); +//! [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 struct member; }; +struct Bar { }; +BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c)); +BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c)); +//! [nested_template] +} + +namespace template_specialization { +//! [template_specialization] +template +struct Foo; + +template +struct Bar; + +auto is_binary_template = hana::is_valid([](auto trait) -> decltype( + trait(hana::type_c, hana::type_c) +) { }); + +BOOST_HANA_CONSTANT_CHECK(is_binary_template(hana::template_)); +BOOST_HANA_CONSTANT_CHECK(!is_binary_template(hana::template_)); +//! [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 + +#include +#include +#include +#include +namespace hana = boost::hana; +using namespace std::literals; + + +//! [utilities] +template +std::string join(Xs&& xs, std::string sep) { + return hana::fold(hana::intersperse(std::forward(xs), sep), "", hana::_ + hana::_); +} + +std::string quote(std::string s) { return "\"" + s + "\""; } + +template +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 + std::enable_if_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(name)) + " : " + to_json(member); + }); + + return "{" + join(std::move(json), ", ") + "}"; +} +//! [Struct] + +//! [Sequence] +template + std::enable_if_t::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 + +#include +#include +namespace hana = boost::hana; + + +struct yes { std::string toString() const { return "yes"; } }; +struct no { }; + +//! [optionalToString.sfinae] +template +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 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +namespace hana = boost::hana; +namespace mpl = boost::mpl; + + +namespace with_mpl { +//! [mpl] +using types = mpl::vector; +using number_of_floats = mpl::fold< + types, + mpl::int_<0>, + mpl::if_, + mpl::next, + mpl::_1 + > +>::type; +static_assert(number_of_floats::value == 3, ""); +//! [mpl] +} + +namespace with_hana { +//! [hana] +constexpr auto types = hana::tuple_t; +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(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 +#include +#include + +struct Fish { std::string name; }; +struct Cat { std::string name; }; +struct Dog { std::string name; }; +//! [additional_setup] + +//! [includes] +#include +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, hana::type_c, hana::type_c); + +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, hana::type_c), ""); +//! [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 + +#include +#include +#include +#include +#include +#include +namespace hana = boost::hana; + +//! [cases] +template +auto case_ = [](auto f) { + return hana::make_pair(hana::type_c, f); +}; + +struct default_t; +auto default_ = case_; +//! [cases] + +//! [process] +template +auto process(Any&, std::type_index const&, Default& default_) { + return default_(); +} + +template +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(&a)) + : process(a, t, default_, rest...); +} +//! [process] + +//! [switch_] +template +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; + }); + 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; + }); + + 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_([](auto i) { return "int: "s + std::to_string(i); }), + case_([](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_([](auto) -> int { return 1; }), + case_([](auto) -> long { return 2l; }), + default_([]() -> long long { return 3ll; }) +); + +// r is inferred to be a long long +static_assert(std::is_same{}, ""); +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 + +#include +#include +#include + +#include +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::type; +Container tuple = fusion::make_vector(1, 'x', 3.4f); + +using Predicate = mpl::quote1; +using Result = fusion::result_of::find_if::type; +Result result = fusion::find_if(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 +#include +#include +#include +#include +#include + +#include +#include +#include +namespace hana = boost::hana; + + +//! [setup] +template +struct print_impl { + template + static void apply(std::ostream&, X const&) { + // possibly some default implementation + } +}; + +template +void print(std::ostream& os, X x) { + using Tag = typename hana::tag_of::type; + print_impl::apply(os, x); +} +//! [setup] + +//! [vector] +struct vector_tag; + +struct vector0 { + using hana_tag = vector_tag; + static constexpr std::size_t size = 0; +}; + +template +struct vector1 { + T1 t1; + using hana_tag = vector_tag; + static constexpr std::size_t size = 1; + + template + auto const& operator[](Index i) const { + static_assert(i == 0u, "index out of bounds"); + return t1; + } +}; + +template +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 + auto const& operator[](Index i) const { + return *hana::make_tuple(&t1, &t2)[i]; + } +}; + +// and so on... +//! [vector] + +//! [customize] +template <> +struct print_impl { + template + static void apply(std::ostream& os, vectorN xs) { + auto N = hana::size_c; + + 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 +struct print_impl> { + template + 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 v1{1}; + print(ss, v1); + BOOST_HANA_RUNTIME_CHECK(ss.str() == "[1]"); + } + + { + std::stringstream ss; + vector2 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 +void print(std::ostream& os, vector1 v) +{ os << "[" << v.t1 << "]"; } + +template +void print(std::ostream& os, vector2 v) +{ os << "[" << v.t1 << ", " << v.t2 << "]"; } + +// and so on... +//! [old_way] +} + +namespace preconditions { +//! [preconditions] +template +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::type; + print_impl::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 + void operator()(std::ostream& os, X x) const { + using Tag = typename hana::tag_of::type; + print_impl::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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +namespace fusion = boost::fusion; +namespace mpl = boost::mpl; +namespace hana = boost::hana; +using namespace hana::literals; + + +template +struct storage { char weight[n]; }; + +int main() { + +{ + +//! [tuple] +auto types = hana::make_tuple(hana::type_c, hana::type_c, hana::type_c); +auto char_ref = types[1_c]; + +BOOST_HANA_CONSTANT_CHECK(char_ref == hana::type_c); +//! [tuple] + +}{ + +//! [filter.MPL] +using types = mpl::vector; +using ts = mpl::copy_if, + std::is_reference>>::type; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// placeholder expression + +static_assert(mpl::equal>::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; + +auto ts = hana::filter(types, [](auto t) { + return is_pointer(t) || is_reference(t); +}); + +BOOST_HANA_CONSTANT_CHECK(ts == hana::tuple_t); +//! [filter.Hana] + +}{ + +//! [single_library.then] +// types (MPL) +using types = mpl::vector; +using ts = mpl::copy_if, + std::is_reference>>::type; + +// values (Fusion) +auto values = fusion::make_vector(1, 'c', nullptr, 3.5); +auto vs = fusion::filter_if>(values); +//! [single_library.then] + +static_assert(mpl::equal>::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; +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); +BOOST_HANA_RUNTIME_CHECK(vs == hana::make_tuple(1, 'c')); + +}{ + +//! [make_map.Fusion] +auto map = fusion::make_map( + "char", "int", "long", "float", "double", "void" +); + +std::string Int = fusion::at_key(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"), + hana::make_pair(hana::type_c, "int"), + hana::make_pair(hana::type_c, "long"), + hana::make_pair(hana::type_c, "float"), + hana::make_pair(hana::type_c, "double") +); + +std::string Int = map[hana::type_c]; +BOOST_HANA_RUNTIME_CHECK(Int == "int"); +//! [make_map.Hana] + +}{ + +using hana::traits::add_pointer; + +//! [skip_first_step] +auto types = hana::tuple_t; // 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); + +}{ + +//! [traits] +BOOST_HANA_CONSTANT_CHECK(hana::traits::add_pointer(hana::type_c) == hana::type_c); +BOOST_HANA_CONSTANT_CHECK(hana::traits::common_type(hana::type_c, hana::type_c) == hana::type_c); +BOOST_HANA_CONSTANT_CHECK(hana::traits::is_integral(hana::type_c)); + +auto types = hana::tuple_t; +BOOST_HANA_CONSTANT_CHECK(hana::all_of(types, hana::traits::is_integral)); +//! [traits] + +}{ + +//! [extent] +auto extent = [](auto t, auto n) { + return std::extent{}; +}; + +BOOST_HANA_CONSTANT_CHECK(extent(hana::type_c, hana::int_c<1>) == hana::size_c<0>); +BOOST_HANA_CONSTANT_CHECK(extent(hana::type_c, hana::int_c<1>) == hana::size_c<2>); +//! [extent] + +} + +} + +namespace mpl_based { +//! [smallest.MPL] +template +struct smallest + : mpl::deref< + typename mpl::min_element< + mpl::vector, + mpl::less, mpl::sizeof_> + >::type + > +{ }; + +template +using smallest_t = typename smallest::type; + +static_assert(std::is_same< + smallest_t, + char +>::value, ""); +//! [smallest.MPL] + +static_assert(std::is_same< + smallest_t, storage<1>, storage<2>>, + storage<1> +>::value, ""); +} // end namespace mpl_based + +namespace hana_based { +//! [smallest.Hana] +template +auto smallest = hana::minimum(hana::make_tuple(hana::type_c...), [](auto t, auto u) { + return hana::sizeof_(t) < hana::sizeof_(u); +}); + +template +using smallest_t = typename decltype(smallest)::type; + +static_assert(std::is_same< + smallest_t, char +>::value, ""); +//! [smallest.Hana] + +static_assert(std::is_same< + smallest_t, storage<1>, storage<2>>, + storage<1> +>::value, ""); +} // end namespace hana_based + + +namespace metafunction1 { +//! [metafunction1] +template