From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- .../hana/example/misc/dimensional_analysis.cpp | 71 +++++ src/boost/libs/hana/example/misc/from_json.cpp | 129 +++++++++ src/boost/libs/hana/example/misc/indexed_sort.cpp | 62 ++++ src/boost/libs/hana/example/misc/infinite_list.cpp | 116 ++++++++ src/boost/libs/hana/example/misc/infinite_set.cpp | 321 +++++++++++++++++++++ src/boost/libs/hana/example/misc/lambda_tuple.cpp | 244 ++++++++++++++++ src/boost/libs/hana/example/misc/nth.cpp | 45 +++ .../libs/hana/example/misc/overload_linearly.cpp | 42 +++ src/boost/libs/hana/example/misc/printf.cpp | 66 +++++ src/boost/libs/hana/example/misc/ref_tuple.cpp | 92 ++++++ .../libs/hana/example/misc/restricted_function.cpp | 143 +++++++++ src/boost/libs/hana/example/misc/tree.cpp | 144 +++++++++ 12 files changed, 1475 insertions(+) create mode 100644 src/boost/libs/hana/example/misc/dimensional_analysis.cpp create mode 100644 src/boost/libs/hana/example/misc/from_json.cpp create mode 100644 src/boost/libs/hana/example/misc/indexed_sort.cpp create mode 100644 src/boost/libs/hana/example/misc/infinite_list.cpp create mode 100644 src/boost/libs/hana/example/misc/infinite_set.cpp create mode 100644 src/boost/libs/hana/example/misc/lambda_tuple.cpp create mode 100644 src/boost/libs/hana/example/misc/nth.cpp create mode 100644 src/boost/libs/hana/example/misc/overload_linearly.cpp create mode 100644 src/boost/libs/hana/example/misc/printf.cpp create mode 100644 src/boost/libs/hana/example/misc/ref_tuple.cpp create mode 100644 src/boost/libs/hana/example/misc/restricted_function.cpp create mode 100644 src/boost/libs/hana/example/misc/tree.cpp (limited to 'src/boost/libs/hana/example/misc') 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 +#include +#include +#include +#include + +#include +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); +using length = decltype(hana::tuple_c); +using time_ = decltype(hana::tuple_c); +using charge = decltype(hana::tuple_c); +using temperature = decltype(hana::tuple_c); +using intensity = decltype(hana::tuple_c); +using amount = decltype(hana::tuple_c); + +// composite dimensions +using velocity = decltype(hana::tuple_c); // M/T +using acceleration = decltype(hana::tuple_c); // M/T^2 +using force = decltype(hana::tuple_c); // ML/T^2 + + +template +struct quantity { + double value_; + + explicit quantity(double v) : value_(v) { } + + template + explicit quantity(quantity other) + : value_(other.value_) + { + static_assert(Dimensions{} == OtherDimensions{}, + "Constructing quantities with incompatible dimensions!"); + } + + explicit operator double() const { return value_; } +}; + +template +auto operator*(quantity a, quantity b) { + using D = decltype(hana::zip_with(std::plus<>{}, D1{}, D2{})); + return quantity{static_cast(a) * static_cast(b)}; +} + +template +auto operator/(quantity a, quantity b) { + using D = decltype(hana::zip_with(std::minus<>{}, D1{}, D2{})); + return quantity{static_cast(a) / static_cast(b)}; +} + +int main() { + quantity m{10.3}; + quantity d{3.6}; + quantity t{2.4}; + quantity v{d / t}; + quantity a{3.9}; + quantity 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +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 + std::enable_if_t::value, +T> from_json(std::istream& in) { + T result; + in >> result; + return result; +} + +template + std::enable_if_t::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 + std::enable_if_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::max(), ':'); + auto& member = hana::at_key(result, key); + using Member = std::remove_reference_t; + member = from_json(in); + }); + in >> brace; + return result; +} + +template + std::enable_if_t::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; + element = from_json(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>(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +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; + 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_) + )::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 + >{}, ""); + + (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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +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 +struct lazy_cons_type { + X x; + Xs xs; + using hana_tag = LazyList; +}; + +auto lazy_cons = [](auto x, auto xs) { + return lazy_cons_type{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 { + template + static constexpr auto apply(Xs&& lcons, N const& n) { + return hana::drop_front(lcons, n).x; + } + }; + + namespace detail { + struct eval_tail { + template + 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 { + template + static constexpr auto apply(Xs&& lcons, N const&) { + return hana::iterate(detail::eval_tail{}, lcons); + } + }; + + template <> + struct is_empty_impl { + template + 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 { + template + static constexpr auto apply(Xs xs, X x) + { return lazy_cons(x, hana::make_lazy(xs)); } + }; + + template <> + struct empty_impl { + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace hana = boost::hana; + + +// A `Monad` for searching infinite sets in finite time. +// +// Taken from http://goo.gl/XJeDy8. +struct infinite_set_tag { }; + +template +struct infinite_set { + Find find; + using hana_tag = infinite_set_tag; +}; + +template +constexpr infinite_set make_infinite_set(Pred pred) { + return {pred}; +} + +template +constexpr auto singleton(X x) { + return make_infinite_set([=](auto /*p*/) { return x; }); +} + +template +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 { + template + static constexpr auto apply(Xs xs, Ys ys) { + return flatten(doubleton(xs, ys)); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Comparable + ////////////////////////////////////////////////////////////////////////// + template <> + struct equal_impl { + template + static constexpr auto apply(Xs xs, Ys ys) + { return and_(is_subset(xs, ys), is_subset(ys, xs)); } + }; + + + ////////////////////////////////////////////////////////////////////////// + // Functor + ////////////////////////////////////////////////////////////////////////// + template <> + struct transform_impl { + template + 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 { + template + static constexpr auto apply(X x) + { return singleton(x); } + }; + + template <> + struct ap_impl { + template + static constexpr auto apply(F fset, Set set) { + return flatten(transform(fset, partial(transform, set))); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Monad + ////////////////////////////////////////////////////////////////////////// + template <> + struct flatten_impl { + template + 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 { + template + 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 { + template + static constexpr auto apply(Set set, Pred p) { + return p(set.find(p)); + } + }; +}} // end namespace boost::hana + +////////////////////////////////////////////////////////////////////////////// +// Tests +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace hana = boost::hana; + + +template +constexpr int n = i; + +template +constexpr auto c = hana::int_c; + +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(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +namespace hana = boost::hana; + + +// An interesting way of implementing tuple using lambda captures. + +struct lambda_tuple_tag { }; + +template +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{std::move(storage)}; +}; + +namespace boost { namespace hana { + ////////////////////////////////////////////////////////////////////////// + // Foldable + ////////////////////////////////////////////////////////////////////////// + template <> + struct unpack_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, F&& f) { + return static_cast(xs).storage(static_cast(f)); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Functor + ////////////////////////////////////////////////////////////////////////// + template <> + struct transform_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, F f) { + return static_cast(xs).storage( + [f(std::move(f))](auto&& ...xs) -> decltype(auto) { + return lambda_tuple(f(static_cast(xs))...); + } + ); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Iterable + ////////////////////////////////////////////////////////////////////////// + template <> + struct front_impl { + template + static constexpr decltype(auto) apply(Xs&& xs) { + return static_cast(xs).storage( + [](auto&& x, auto&& ...) -> decltype(auto) { + return id(static_cast(x)); + } + ); + } + }; + + template <> + struct is_empty_impl { + template + static constexpr decltype(auto) apply(Xs&& xs) { + return static_cast(xs).storage( + [](auto const& ...xs) -> decltype(auto) { + return hana::bool_c; + } + ); + } + }; + + template <> + struct at_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, Index const&) { + return static_cast(xs).storage( + detail::variadic::at + ); + } + }; + + template <> + struct drop_front_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, N const& n) { + auto m = min(n, length(xs)); + return static_cast(xs).storage( + detail::variadic::drop_into(lambda_tuple) + ); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // MonadPlus + ////////////////////////////////////////////////////////////////////////// + template <> + struct concat_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, Ys&& ys) { + return static_cast(xs).storage( + [ys(static_cast(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(ys)... + ); + } + ); + } + ); + } + }; + + template <> + struct prepend_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, X&& x) { + return static_cast(xs).storage( + [x(static_cast(x))](auto&& ...xs) -> decltype(auto) { + return lambda_tuple( + std::move(x), + static_cast(xs)... + ); + } + ); + } + }; + + template <> + struct append_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, X&& x) { + return static_cast(xs).storage( + [x(static_cast(x))](auto&& ...xs) -> decltype(auto) { + return lambda_tuple( + static_cast(xs)..., + std::move(x) + ); + } + ); + } + }; + + template <> + struct empty_impl { + static BOOST_HANA_CONSTEXPR_LAMBDA decltype(auto) apply() { + return lambda_tuple(); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Sequence + ////////////////////////////////////////////////////////////////////////// + template <> + struct Sequence { + static constexpr bool value = true; + }; + + template <> + struct take_front_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, N const& n) { + auto m = min(n, length(xs)); + return static_cast(xs).storage( + detail::variadic::take + )(lambda_tuple); + } + }; + + template <> + struct zip_shortest_with_impl { + template + 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 { + template + static constexpr decltype(auto) apply(Xs&& ...xs) { + return lambda_tuple(static_cast(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 + +#include +#include +namespace hana = boost::hana; + + +constexpr int to_int(char c) +{ return static_cast(c) - 48; } + +template +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 +struct pick { + static constexpr unsigned long n = parse({c...}); + + template + constexpr auto operator()(T&& ...args) const + { return hana::arg(std::forward(args)...); } +}; + +template constexpr pick operator"" _st() { return {}; } +template constexpr pick operator"" _nd() { return {}; } +template constexpr pick operator"" _rd() { return {}; } +template constexpr pick 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 +#include +#include +#include +#include +#include +#include + +#include +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(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +namespace hana = boost::hana; + + +constexpr auto formats = hana::make_map( + hana::make_pair(hana::type_c, hana::string_c<'%', 'd'>), + hana::make_pair(hana::type_c, hana::string_c<'%', 'f'>), + hana::make_pair(hana::type_c, hana::string_c<'%', 's'>) +); + +template +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::compose(hana::partial(hana::at_key, formats), hana::typeid_) + ); + + auto format_string = hana::sum(format_string_tokens); + auto variables = hana::filter(tokens, hana::compose(hana::not_, hana::is_a)); + 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(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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +namespace hana = boost::hana; + + +// A tuple that holds reference_wrappers to its elements, instead of the +// elements themselves. + +struct RefTuple { }; + +template +struct ref_tuple; + +template +struct ref_tuple { + hana::tuple...> storage_; +}; + + +namespace boost { namespace hana { + template + struct tag_of> { + using type = RefTuple; + }; + + template <> + struct make_impl { + template + static constexpr auto apply(T& ...t) { + return ref_tuple{{std::ref(t)...}}; + } + }; + + template <> + struct at_impl { + template + static constexpr decltype(auto) apply(Xs&& xs, N const& n) { + return hana::at(static_cast(xs).storage_, n).get(); + } + }; + + template <> + struct is_empty_impl { + template + static constexpr auto apply(Xs const& xs) { + return hana::is_empty(xs.storage_); + } + }; + + template <> + struct drop_front_impl { + template + static constexpr auto helper(ref_tuple xs, std::index_sequence) { + return hana::make(hana::at_c(xs.storage_).get()...); + } + + template + static constexpr auto apply(ref_tuple xs, N const&) { + return helper(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 refs = hana::make(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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +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 +struct function_type { + using hana_tag = Function; + + Domain domain_; + Codomain codomain_; + F f_; + + template + constexpr auto operator()(X x) const { + BOOST_HANA_CONSTANT_ASSERT(boost::hana::contains(domain_, x)); + return f_(x); + } +}; + +template +constexpr auto operator==(function_type f, function_type g) +{ return hana::equal(f, g); } + +template +constexpr auto operator!=(function_type f, function_type g) +{ return hana::not_equal(f, g); } + + +auto function = [](auto domain, auto codomain) { + return [=](auto definition) { + return function_type{ + domain, codomain, definition + }; + }; +}; + +template +constexpr auto domain(Function f) +{ return f.domain_; } + +template +constexpr auto codomain(Function f) +{ return f.codomain_; } + +template +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 +constexpr auto implies(P p, Q q) { + return hana::or_(hana::not_(p), q); +} + +template +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 +constexpr auto is_onto(F f) { + return codomain(f) == range(f); +} + +namespace boost { namespace hana { + template <> + struct equal_impl { + template + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace hana = boost::hana; + + +struct tree_tag; + +template +struct node { + X value; + Subforest subforest; + + using hana_tag = tree_tag; +}; + +constexpr auto make_forest = hana::make_tuple; + +template +constexpr auto make_node(X x, Subforest subforest) { + return node{x, subforest}; +} + +namespace boost { namespace hana { + ////////////////////////////////////////////////////////////////////////// + // Comparable + ////////////////////////////////////////////////////////////////////////// + template <> + struct equal_impl { + template + 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 { + template + 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 { + template + static constexpr auto apply(X x) + { return make_node(x, make_forest()); } + }; + + template <> + struct ap_impl { + template + 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 { + template + 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 { + template + 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()) + )) + )); +} -- cgit v1.2.3