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