diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 2421fdaf2..3611812b3 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -43,6 +43,7 @@ boost_hana_add_example(list.filter) boost_hana_add_example(list.foldable.all) boost_hana_add_example(list.foldable.any) boost_hana_add_example(list.foldable.count) +boost_hana_add_example(list.foldable.find) boost_hana_add_example(list.foldable.foldl) boost_hana_add_example(list.foldable.foldl1) boost_hana_add_example(list.foldable.foldr) @@ -56,7 +57,6 @@ boost_hana_add_example(list.functor.fmap) boost_hana_add_example(list.init) boost_hana_add_example(list.iterable.at) boost_hana_add_example(list.iterable.drop) -boost_hana_add_example(list.iterable.find) boost_hana_add_example(list.iterable.overview) boost_hana_add_example(list.list_c) boost_hana_add_example(list.list_t) @@ -78,6 +78,7 @@ boost_hana_add_example(maybe.comparable) boost_hana_add_example(maybe.functor) boost_hana_add_example(maybe.monad) +boost_hana_add_example(range.foldable.lazy_foldl) boost_hana_add_example(range.foldable.lazy_foldr) boost_hana_add_example(range.foldable.product) boost_hana_add_example(range.iterable.drop_while) diff --git a/example/list/iterable/find.cpp b/example/list/foldable/find.cpp similarity index 100% rename from example/list/iterable/find.cpp rename to example/list/foldable/find.cpp diff --git a/example/range/foldable/lazy_foldl.cpp b/example/range/foldable/lazy_foldl.cpp new file mode 100644 index 000000000..3c4ff1d9e --- /dev/null +++ b/example/range/foldable/lazy_foldl.cpp @@ -0,0 +1,33 @@ +/* +@copyright Louis Dionne 2014 +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 +using namespace boost::hana; +using namespace literals; + + +int main() { + //! [main] + auto to_string = [](auto x) { return (std::ostringstream{} << x).str(); }; + + auto down_to = [=](auto n) { + return [=](auto x, auto y) { + auto x_ = if_(y() == n, always("..."), x)(); + return "(" + to_string(x_) + " + " + to_string(y()) + ")"; + }; + }; + + assert( + lazy_foldl(down_to(4_c), 1_c, range(2_c, 8_c)) == "((((... + 4) + 5) + 6) + 7)" + ); + //! [main] +} diff --git a/example/range/foldable/lazy_foldr.cpp b/example/range/foldable/lazy_foldr.cpp index b52d63234..a9d4830a9 100644 --- a/example/range/foldable/lazy_foldr.cpp +++ b/example/range/foldable/lazy_foldr.cpp @@ -19,12 +19,16 @@ int main() { //! [main] auto to_string = [](auto x) { return (std::ostringstream{} << x).str(); }; - auto show = [=](auto x, auto y) { - auto y_ = if_(x() < 4_c, y, always("..."))(); - return "(" + to_string(x()) + " + " + to_string(y_) + ")"; + auto up_to = [=](auto n) { + return [=](auto x, auto y) { + auto y_ = if_(x() == n, always("..."), y)(); + return "(" + to_string(x()) + " + " + to_string(y_) + ")"; + }; }; - auto state = [] { assert(false); }; // this will never be evaluated - assert(lazy_foldr(show, state, range(1_c, 999999_c)) == "(1 + (2 + (3 + (4 + ...))))"); + constexpr struct { } state{}; // this will never be evaluated + assert( + lazy_foldr(up_to(4_c), state, range(1_c, 999999_c)) == "(1 + (2 + (3 + (4 + ...))))" + ); //! [main] } diff --git a/include/boost/hana/foldable.hpp b/include/boost/hana/foldable.hpp index 6dcc0bef6..e6bc5d963 100644 --- a/include/boost/hana/foldable.hpp +++ b/include/boost/hana/foldable.hpp @@ -15,6 +15,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include namespace boost { namespace hana { @@ -25,11 +26,7 @@ namespace boost { namespace hana { -------------------------------------------------------------------------- ## Minimal complete definition - `foldl`, `foldl1`, `foldr1` and `lazy_foldr` - - -------------------------------------------------------------------------- - - @todo Reduce the mcd. + `lazy_foldr` */ template struct Foldable; @@ -79,11 +76,11 @@ namespace boost { namespace hana { }; //! Lazy right-associative fold of a structure using a binary operation. + //! @method{Foldable} //! //! Unlike for strict folds, the binary operation should take nullary //! functions returning an element and the state instead of taking an //! element and the state directly. - //! @method{Foldable} //! //! ### Example //! @snippet example/range/foldable/lazy_foldr.cpp main @@ -95,6 +92,42 @@ namespace boost { namespace hana { return Foldable>::lazy_foldr_impl(f, state, foldable); }; + //! Lazy left-associative fold of a structure using a binary operation. + //! @method{Foldable} + //! + //! Unlike for strict folds, the binary operation should take nullary + //! functions returning the state and an element instead of taking the + //! state and an element directly. + //! + //! @warning + //! It is important to be aware that a lazy left fold must still walk the + //! whole structure before it can return. This is because of the nature of + //! left-folds, which are always equivalent to + //! @code + //! foldl(f, state, structure): + //! if (some_stop_condition) + //! return state + //! else + //! return foldl(f, f(...), ...); + //! @endcode + //! Notice how `foldl` calls itself recursively in the `else` branch; this + //! means that the next invocation of `foldl` is always needed, and so the + //! whole structure has to be unfolded. When `f` is lazy, this has the + //! effect of creating a (potentially huge) chain of "thunks": + //! @code + //! f(f(f(f(f(x1, state), x2), x3), x4), x5) + //! @endcode + //! This chain is then only evaluated lazily, but creating the chain + //! itself can cause a stack overflow. If you don't need to accumulate + //! the result lazily, consider using `foldl` instead, which does not + //! create a chain of thunks and evaluates `f` as it goes. + //! + //! ### Example + //! @snippet example/range/foldable/lazy_foldl.cpp main + BOOST_HANA_CONSTEXPR_LAMBDA auto lazy_foldl = [](auto f, auto state, auto foldable) { + return Foldable>::lazy_foldl_impl(f, state, foldable); + }; + //! Return the number of elements in a finite structure. //! @method{Foldable} //! @@ -164,6 +197,21 @@ namespace boost { namespace hana { return Foldable>::count_impl(predicate, foldable); }; + //! Find an element satisfying a predicate in the structure. + //! @method{Foldable} + //! + //! Specifically, returns `just` the first element satisfying the + //! `predicate`, or `nothing` if there is no such element. + //! + //! ### Fusion example + //! @snippet example/list/foldable/find.cpp fusion + //! + //! ### MPL example + //! @snippet example/list/foldable/find.cpp mpl + BOOST_HANA_CONSTEXPR_LAMBDA auto find = [](auto predicate, auto foldable) { + return Foldable>::find_impl(predicate, foldable); + }; + //! Invoke a function with the elements of a structure as arguments. //! @method{Foldable} //! @@ -235,19 +283,57 @@ namespace boost { namespace hana { static constexpr auto foldr_impl(F f, State s, Foldable_ foldable) { return lazy_foldr(on(f, apply), s, foldable); } - template - static constexpr auto length_impl(Foldable_ foldable) { - auto incr = [](auto n, auto) { return n + size_t<1>; }; - return foldl(incr, size_t<0>, foldable); + template + static constexpr auto foldr1_impl(F f, Foldable_ foldable) { + auto maybe_f = [=](auto lx, auto my) { + return just(maybe(lx(), partial(f, lx()), my())); + }; + return from_just(lazy_foldr(maybe_f, nothing, foldable)); + } + + template + static constexpr auto foldl_impl(F f, State s, Foldable_ foldable) { + auto f_ = [=](auto x, auto next) { + return [=](auto state) { + return next()(f(state, x())); + }; + }; + return lazy_foldr(f_, id, foldable)(s); + } + + template + static constexpr auto foldl1_impl(F f, Foldable_ foldable) { + auto maybe_f = [=](auto mx, auto ly) { + return maybe( + just(ly()), + [=](auto x) { return just(f(x, ly())); }, + mx() + ); + }; + return from_just(lazy_foldl(maybe_f, nothing, foldable)); + } + + template + static constexpr auto lazy_foldl_impl(F f, State s, Foldable_ foldable) { + auto f_ = [=](auto lx, auto lnext) { + return [=](auto state) { + return lnext()(f([=] { return state; }, lx)); + }; + }; + return lazy_foldr(f_, id, foldable)(s); } + template + static constexpr auto length_impl(Foldable_ foldable) + { return foldl(_ + size_t<1>, size_t<0>, foldable); } + template static constexpr auto minimum_impl(Foldable_ foldable) - { return minimum_by([](auto x, auto y) { return x < y; }, foldable); } + { return minimum_by(_ < _, foldable); } template static constexpr auto maximum_impl(Foldable_ foldable) - { return maximum_by([](auto x, auto y) { return x < y; }, foldable); } + { return maximum_by(_ < _, foldable); } template static constexpr auto minimum_by_impl(Pred pred, Foldable_ foldable) { @@ -265,18 +351,32 @@ namespace boost { namespace hana { ); } + template + static constexpr auto find_impl(Pred pred, Foldable_ foldable) { + auto go = [=](auto x, auto tail) { + return eval_if(pred(x()), + always(just(x())), + [=](auto id) { return id(tail)(); } + ); + }; + return lazy_foldr(go, nothing, foldable); + } + template static constexpr auto sum_impl(Foldable_ foldable) - { return foldl([](auto x, auto y) { return x + y; }, int_<0>, foldable); } + { return foldl(_ + _, int_<0>, foldable); } template static constexpr auto product_impl(Foldable_ foldable) - { return foldl([](auto x, auto y) { return x * y; }, int_<1>, foldable); } + { return foldl(_ * _, int_<1>, foldable); } template static constexpr auto count_impl(Pred pred, Foldable_ foldable) { auto inc = [=](auto counter, auto x) { - return if_(pred(x), counter + size_t<1>, counter); + //! @todo + //! We use `!!pred(x)` to allow ints and other stuff. + //! Remove this once we get a proper `Logical` type class. + return if_(!!pred(x), counter + size_t<1>, counter); }; return foldl(inc, size_t<0>, foldable); } @@ -285,30 +385,15 @@ namespace boost { namespace hana { static constexpr auto unpack_impl(F f, Foldable_ foldable) { return foldl(partial, f, foldable)(); } - template - struct lazy_or { - Pred p; - template - constexpr auto operator()(X x, Y y) const - { return call(p(x()), y); } - - template - constexpr auto call(decltype(true_), Y y) const - { return true_; } - - template - constexpr auto call(decltype(false_), Y y) const - { return y(); } - - template - constexpr auto call(bool b, Y y) const - { return b ? b : y(); } - }; // any, all, none template static constexpr auto any_impl(Pred pred, Foldable_ foldable) { - return lazy_foldr(lazy_or{pred}, false_, foldable); + auto lazy_or = [=](auto lx, auto ly) { + auto p = pred(lx()); + return eval_if(p, always(p), [=](auto _) { return _(ly)(); }); + }; + return lazy_foldr(lazy_or, false_, foldable); } template @@ -343,8 +428,6 @@ namespace boost { namespace hana { template struct Foldable : instance::template with { }; - - //! @} }} // end namespace boost::hana #endif // !BOOST_HANA_FOLDABLE_HPP diff --git a/include/boost/hana/iterable.hpp b/include/boost/hana/iterable.hpp index 0b7d0ee55..d18d3e57a 100644 --- a/include/boost/hana/iterable.hpp +++ b/include/boost/hana/iterable.hpp @@ -154,19 +154,6 @@ namespace boost { namespace hana { return Iterable>::drop_until_impl(predicate, iterable); }; - //! Return `just` the first element satisfying the `predicate`, or `nothing` - //! if there is no such element. - //! @method{Iterable} - //! - //! ### Fusion example - //! @snippet example/list/iterable/find.cpp fusion - //! - //! ### MPL example - //! @snippet example/list/iterable/find.cpp mpl - BOOST_HANA_CONSTEXPR_LAMBDA auto find = [](auto predicate, auto iterable) { - return Iterable>::find_impl(predicate, iterable); - }; - template <> struct instance { template @@ -218,15 +205,6 @@ namespace boost { namespace hana { static constexpr auto drop_until_impl(Pred pred, Iterable_ iterable) { return drop_while([=](auto x) { return !pred(x); }, iterable); } - - template - static constexpr auto find_impl(Pred pred, Iterable_ iterable) { - auto e = drop_until(pred, iterable); - return if_(is_empty(e), - always(nothing), - compose(just, head) - )(e); - } }; }; @@ -305,6 +283,15 @@ namespace boost { namespace hana { } ); } + + template + static constexpr auto find_impl(Pred pred, Iterable_ xs) { + auto e = drop_until(pred, xs); + return eval_if(is_empty(e), + always(nothing), + [=](auto _) { return just(_(head)(e)); } + ); + } }; }} // end namespace boost::hana diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a651d5d06..ee0348a59 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,7 +30,12 @@ boost_hana_add_test(detail.left_folds) boost_hana_add_test(foldable.all_of) boost_hana_add_test(foldable.count) +boost_hana_add_test(foldable.find) +boost_hana_add_test(foldable.foldl) +boost_hana_add_test(foldable.foldl1) boost_hana_add_test(foldable.foldr) +boost_hana_add_test(foldable.foldr1) +boost_hana_add_test(foldable.lazy_foldl) boost_hana_add_test(foldable.length) boost_hana_add_test(foldable.maximum) boost_hana_add_test(foldable.minimum) @@ -65,7 +70,6 @@ boost_hana_add_test(iterable.comparable) boost_hana_add_test(iterable.drop) boost_hana_add_test(iterable.drop_until) boost_hana_add_test(iterable.drop_while) -boost_hana_add_test(iterable.find) boost_hana_add_test(iterable.foldable) boost_hana_add_test(iterable.last) diff --git a/test/foldable/all_of.cpp b/test/foldable/all_of.cpp index 8f714d431..0634a0749 100644 --- a/test/foldable/all_of.cpp +++ b/test/foldable/all_of.cpp @@ -8,29 +8,78 @@ Distributed under the Boost Software License, Version 1.0. #include #include +#include #include "minimal_foldable.hpp" +#include using namespace boost::hana; -constexpr struct { } invalid_type{}; -constexpr struct { - constexpr operator bool() const { return *this; } -} invalid_value{}; +struct invalid_value { + using hana_datatype = invalid_value; + //! @todo This should be part of Logical's mcd. + invalid_value operator!() const { assert(false); return *this; } +}; +struct invalid_type { }; + +namespace boost { namespace hana { + template <> + struct Logical : defaults::with { + template + static bool eval_if_impl(invalid_value, T, F) + { assert(false); return true; } + }; +}} int main() { + // purely compile-time BOOST_HANA_STATIC_ASSERT(all_of(foldable())); - BOOST_HANA_STATIC_ASSERT(all_of(foldable(true_))); - BOOST_HANA_STATIC_ASSERT(all_of(foldable(true_, true_))); - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(true_, true_, false_))); - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(false_, true_, true_))); + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>))); - BOOST_HANA_STATIC_ASSERT(all_of(foldable(true, true))); - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(true, true, false))); + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int_<1>, char_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<1>, char_<0>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<0>))); - // test short-circuiting - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(false_, invalid_type))); + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int_<1>, char_<1>, long_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<1>, char_<1>, long_<0>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<1>, char_<0>, long_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<1>, char_<0>, long_<0>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<1>, long_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<1>, long_<0>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<0>, long_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, char_<0>, long_<0>))); - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(false_, invalid_value))); - BOOST_HANA_STATIC_ASSERT(!all_of(foldable(false, invalid_value))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<0>, invalid_type{}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int_<1>, long_<0>, invalid_type{}))); + + + // constexpr/runtime + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}))); + + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int{1}, char{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, char{0}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{0}))); + + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int{1}, char{1}, double{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, char{1}, double{0}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, char{0}, double{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, char{0}, double{0}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{1}, double{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{1}, double{0}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{0}, double{1}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, char{0}, double{0}))); + + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, invalid_value{}))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, long{0}, invalid_value{}))); + + + // mixed + BOOST_HANA_STATIC_ASSERT( all_of(foldable(int{1}, int_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{1}, int_<0>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, int_<1>))); + BOOST_HANA_STATIC_ASSERT(!all_of(foldable(int{0}, int_<0>))); } diff --git a/test/foldable/count.cpp b/test/foldable/count.cpp index f9db10a3e..02adaf6ab 100644 --- a/test/foldable/count.cpp +++ b/test/foldable/count.cpp @@ -6,30 +6,54 @@ Distributed under the Boost Software License, Version 1.0. #include +#include #include -#include #include #include "minimal_foldable.hpp" using namespace boost::hana; +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto x) { + return x; +}; + int main() { - BOOST_HANA_STATIC_ASSERT(count(id, foldable()) == size_t<0>); + // compile-time + BOOST_HANA_STATIC_ASSERT(count(f, foldable()) == size_t<0>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>)) == size_t<0>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_)) == size_t<1>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(false_)) == size_t<0>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<1>)) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<0>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<1>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<0>)) == size_t<0>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, true_)) == size_t<2>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, false_)) == size_t<1>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(false_, true_)) == size_t<1>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(false_, false_)) == size_t<0>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<1>, long_<1>)) == size_t<3>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<1>, long_<0>)) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<0>, long_<1>)) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<1>, char_<0>, long_<0>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<1>, long_<1>)) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<1>, long_<0>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<0>, long_<1>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int_<0>, char_<0>, long_<0>)) == size_t<0>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, true_, true_)) == size_t<3>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, true_, false_)) == size_t<2>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, false_, true_)) == size_t<2>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true_, false_, false_)) == size_t<1>); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true, true)) == 2); - BOOST_HANA_STATIC_ASSERT(count(id, foldable(true, false)) == 1); + // constexpr/runtime + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0})) == 0); + + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{1})) == 2); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{0})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{1})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{0})) == 0); + + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{1}, double{1})) == 3); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{1}, double{0})) == 2); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{0}, double{1})) == 2); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{1}, char{0}, double{0})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{1}, double{1})) == 2); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{1}, double{0})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{0}, double{1})) == 1); + BOOST_HANA_STATIC_ASSERT(count(f, foldable(int{0}, char{0}, double{0})) == 0); } diff --git a/test/foldable/find.cpp b/test/foldable/find.cpp new file mode 100644 index 000000000..c672d8be5 --- /dev/null +++ b/test/foldable/find.cpp @@ -0,0 +1,43 @@ +/* +@copyright Louis Dionne 2014 +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 "minimal_foldable.hpp" +using namespace boost::hana; + + +int main() { + constexpr struct { } invalid{}; + + BOOST_HANA_STATIC_ASSERT(find(id, foldable()) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<1>)) == just(int_<1>)); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>)) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<1>, invalid)) == just(int_<1>)); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>, int_<2>)) == just(int_<2>)); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>, int_<0>)) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>, int_<2>, invalid)) == just(int_<2>)); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>, int_<0>, int_<3>)) == just(int_<3>)); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int_<0>, int_<0>, int_<0>)) == nothing); + +#if 0 + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{1})) == just(int{1})); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{0})) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{1}, long{1})) == just(int{1})); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{1}, long{0})) == just(int{1})); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{0}, long{1})) == just(long{1})); + BOOST_HANA_STATIC_ASSERT(find(id, foldable(int{0}, long{0})) == nothing); +#endif +} diff --git a/test/foldable/foldl.cpp b/test/foldable/foldl.cpp new file mode 100644 index 000000000..b29be9c23 --- /dev/null +++ b/test/foldable/foldl.cpp @@ -0,0 +1,34 @@ +/* +@copyright Louis Dionne 2014 +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 "minimal_foldable.hpp" +#include +using namespace boost::hana; + + +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto xs, auto x) { + return std::tuple_cat(xs, std::make_tuple(x)); +}; + +int main() { + constexpr std::tuple<> s; + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable()) == s); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(1)) == f(s, 1)); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(1, '2')) == f(f(s, 1), '2')); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(1, '2', 3.3)) == f(f(f(s, 1), '2'), 3.3)); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(1, '2', 3.3, 4.4f)) == f(f(f(f(s, 1), '2'), 3.3), 4.4f)); + + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(int_<1>)) == f(s, int_<1>)); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(int_<1>, int_<2>)) == f(f(s, int_<1>), int_<2>)); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(int_<1>, int_<2>, int_<3>)) == f(f(f(s, int_<1>), int_<2>), int_<3>)); + BOOST_HANA_STATIC_ASSERT(foldl(f, s, foldable(int_<1>, int_<2>, int_<3>, int_<4>)) == f(f(f(f(s, int_<1>), int_<2>), int_<3>), int_<4>)); +} diff --git a/test/foldable/foldl1.cpp b/test/foldable/foldl1.cpp new file mode 100644 index 000000000..b0c70dc4f --- /dev/null +++ b/test/foldable/foldl1.cpp @@ -0,0 +1,38 @@ +/* +@copyright Louis Dionne 2014 +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 "minimal_foldable.hpp" +using namespace boost::hana; + + +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto xs, auto x) { + return std::tuple_cat(xs, std::make_tuple(x)); +}; + +int main() { + { + constexpr auto s = std::make_tuple(1); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s)) == s); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, '2')) == f(s, '2')); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, '2', 3.3)) == f(f(s, '2'), 3.3)); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, '2', 3.3, 4.4f)) == f(f(f(s, '2'), 3.3), 4.4f)); + } + + { + constexpr auto s = std::make_tuple(int_<1>); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s)) == s); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, int_<2>)) == f(s, int_<2>)); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, int_<2>, int_<3>)) == f(f(s, int_<2>), int_<3>)); + BOOST_HANA_STATIC_ASSERT(foldl1(f, foldable(s, int_<2>, int_<3>, int_<4>)) == f(f(f(s, int_<2>), int_<3>), int_<4>)); + } +} diff --git a/test/foldable/foldr.cpp b/test/foldable/foldr.cpp index 9284a2985..1cfee8961 100644 --- a/test/foldable/foldr.cpp +++ b/test/foldable/foldr.cpp @@ -6,18 +6,29 @@ Distributed under the Boost Software License, Version 1.0. #include +#include #include #include -#include #include "minimal_foldable.hpp" +#include using namespace boost::hana; +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto x, auto xs) { + return std::tuple_cat(std::make_tuple(x), xs); +}; + int main() { - BOOST_HANA_STATIC_ASSERT(foldr(cons, list(), foldable()) == list()); - BOOST_HANA_STATIC_ASSERT(foldr(cons, list(), foldable(int_<0>)) == list_c); - BOOST_HANA_STATIC_ASSERT(foldr(cons, list(), foldable(int_<0>, int_<1>)) == list_c); - BOOST_HANA_STATIC_ASSERT(foldr(cons, list(), foldable(int_<0>, int_<1>, int_<2>)) == list_c); - BOOST_HANA_STATIC_ASSERT(foldr(cons, list(), foldable(int_<0>, int_<1>, int_<2>, int_<3>)) == list_c); + constexpr std::tuple<> s; + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable()) == s); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(1)) == f(1, s)); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(1, '2')) == f(1, f('2', s))); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(1, '2', 3.3)) == f(1, f('2', f(3.3, s)))); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(1, '2', 3.3, 4.4f)) == f(1, f('2', f(3.3, f(4.4f, s))))); + + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(int_<0>)) == f(int_<0>, s)); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(int_<0>, int_<1>)) == f(int_<0>, f(int_<1>, s))); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(int_<0>, int_<1>, int_<2>)) == f(int_<0>, f(int_<1>, f(int_<2>, s)))); + BOOST_HANA_STATIC_ASSERT(foldr(f, s, foldable(int_<0>, int_<1>, int_<2>, int_<3>)) == f(int_<0>, f(int_<1>, f(int_<2>, f(int_<3>, s))))); } diff --git a/test/foldable/foldr1.cpp b/test/foldable/foldr1.cpp new file mode 100644 index 000000000..d6128f89d --- /dev/null +++ b/test/foldable/foldr1.cpp @@ -0,0 +1,36 @@ +/* +@copyright Louis Dionne 2014 +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 "minimal_foldable.hpp" +#include +using namespace boost::hana; + + +BOOST_HANA_CONSTEXPR_LAMBDA auto tup = [](auto ...xs) { + return std::make_tuple(xs...); +}; + +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto x, auto xs) { + return std::tuple_cat(tup(x), xs); +}; + +int main() { + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(tup(1))) == tup(1)); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(1, tup('2'))) == f(1, tup('2'))); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(1, '2', tup(3.3))) == f(1, f('2', tup(3.3)))); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(1, '2', 3.3, tup(4.4f))) == f(1, f('2', f(3.3, tup(4.4f))))); + + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(tup(int_<1>))) == tup(int_<1>)); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(int_<1>, tup(int_<2>))) == f(int_<1>, tup(int_<2>))); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(int_<1>, int_<2>, tup(int_<3>))) == f(int_<1>, f(int_<2>, tup(int_<3>)))); + BOOST_HANA_STATIC_ASSERT(foldr1(f, foldable(int_<1>, int_<2>, int_<3>, tup(int_<4>))) == f(int_<1>, f(int_<2>, f(int_<3>, tup(int_<4>))))); +} diff --git a/test/foldable/lazy_foldl.cpp b/test/foldable/lazy_foldl.cpp new file mode 100644 index 000000000..a80a4e73e --- /dev/null +++ b/test/foldable/lazy_foldl.cpp @@ -0,0 +1,38 @@ +/* +@copyright Louis Dionne 2014 +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 "minimal_foldable.hpp" +#include +using namespace boost::hana; + + +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto xs, auto x) { + return std::tuple_cat(xs, std::make_tuple(x)); +}; + +BOOST_HANA_CONSTEXPR_LAMBDA auto lf = [](auto xs, auto x) { + return f(xs(), x()); +}; + +int main() { + constexpr std::tuple<> s{}; + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable()) == s); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(1)) == f(s, 1)); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(1, '2')) == f(f(s, 1), '2')); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(1, '2', 3.3)) == f(f(f(s, 1), '2'), 3.3)); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(1, '2', 3.3, 4.4f)) == f(f(f(f(s, 1), '2'), 3.3), 4.4f)); + + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(int_<0>)) == f(s, int_<0>)); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(int_<0>, int_<1>)) == f(f(s, int_<0>), int_<1>)); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(int_<0>, int_<1>, int_<2>)) == f(f(f(s, int_<0>), int_<1>), int_<2>)); + BOOST_HANA_STATIC_ASSERT(lazy_foldl(lf, s, foldable(int_<0>, int_<1>, int_<2>, int_<3>)) == f(f(f(f(s, int_<0>), int_<1>), int_<2>), int_<3>)); +} diff --git a/test/foldable/length.cpp b/test/foldable/length.cpp index 29b03b2ac..b7cfbc95e 100644 --- a/test/foldable/length.cpp +++ b/test/foldable/length.cpp @@ -14,8 +14,15 @@ using namespace boost::hana; int main() { - BOOST_HANA_STATIC_ASSERT(length(foldable()) == int_<0>); - BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>)) == int_<1>); - BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>, int_<1>)) == int_<2>); - BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>, int_<1>, int_<2>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(length(foldable()) == size_t<0>); + BOOST_HANA_STATIC_ASSERT(length(foldable(1)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(length(foldable(1, '2')) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(length(foldable(1, '2', 3.3)) == size_t<3>); + BOOST_HANA_STATIC_ASSERT(length(foldable(1, '2', 3.3, 4.4f)) == size_t<4>); + BOOST_HANA_STATIC_ASSERT(length(foldable(1, '2', 3.3, 4.4f, nullptr)) == size_t<5>); + + BOOST_HANA_STATIC_ASSERT(length(foldable()) == size_t<0>); + BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>)) == size_t<1>); + BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>, int_<1>)) == size_t<2>); + BOOST_HANA_STATIC_ASSERT(length(foldable(int_<0>, int_<1>, int_<2>)) == size_t<3>); } diff --git a/test/foldable/maximum.cpp b/test/foldable/maximum.cpp index 4905cea0d..8d23c9b71 100644 --- a/test/foldable/maximum.cpp +++ b/test/foldable/maximum.cpp @@ -8,19 +8,65 @@ Distributed under the Boost Software License, Version 1.0. #include #include -#include #include "minimal_foldable.hpp" using namespace boost::hana; int main() { + // compile-time BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>)) == int_<0>); - BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<1>)) == int_<1>); - BOOST_HANA_STATIC_ASSERT(decltype_(maximum(foldable(int_<1>, int_<0>))) == decltype_(int_<1>)); - BOOST_HANA_STATIC_ASSERT(maximum(foldable(0)) == 0); - BOOST_HANA_STATIC_ASSERT(maximum(foldable(0, 1)) == 1); - BOOST_HANA_STATIC_ASSERT(maximum(foldable(1, 0)) == 1); - BOOST_HANA_STATIC_ASSERT(maximum(foldable(1, 0, int_<-2>, 15)) == 15); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<1>)) == int_<1>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<0>)) == int_<1>); + + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<1>, int_<2>)) == int_<2>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<0>, int_<2>)) == int_<2>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<2>, int_<0>)) == int_<2>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<2>, int_<1>, int_<0>)) == int_<2>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<2>, int_<0>, int_<1>)) == int_<2>); + + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<1>, int_<2>, int_<3>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<0>, int_<2>, int_<3>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<2>, int_<0>, int_<3>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<1>, int_<2>, int_<3>, int_<0>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<2>, int_<1>, int_<3>, int_<0>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<2>, int_<3>, int_<1>, int_<0>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<2>, int_<3>, int_<0>, int_<1>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<3>, int_<2>, int_<0>, int_<1>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<3>, int_<0>, int_<2>, int_<1>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<3>, int_<0>, int_<1>, int_<2>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<2>, int_<3>, int_<1>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int_<0>, int_<3>, int_<1>, int_<2>)) == int_<3>); + + + // constexpr/runtime + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0})) == int{0}); + + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{1})) == char{1}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{0})) == int{1}); + + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{1}, long{2})) == long{2}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{0}, long{2})) == long{2}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{2}, long{0})) == char{2}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{2}, char{1}, long{0})) == int{2}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{2}, char{0}, long{1})) == int{2}); + + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{1}, long{2}, double{3})) == double{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{0}, long{2}, double{3})) == double{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{2}, long{0}, double{3})) == double{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{1}, char{2}, long{3}, double{0})) == long{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{2}, char{1}, long{3}, double{0})) == long{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{2}, char{3}, long{1}, double{0})) == char{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{2}, char{3}, long{0}, double{1})) == char{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{3}, char{2}, long{0}, double{1})) == int{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{3}, char{0}, long{2}, double{1})) == int{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{3}, char{0}, long{1}, double{2})) == int{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{2}, long{3}, double{1})) == long{3}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{3}, long{1}, double{2})) == char{3}); + + + // mixed + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, char{1}, long_<2>)) == long{2}); + BOOST_HANA_STATIC_ASSERT(maximum(foldable(int{0}, long_<1>, char{2})) == char{2}); } diff --git a/test/foldable/minimal_foldable.hpp b/test/foldable/minimal_foldable.hpp index a862af62d..d9cb142c0 100644 --- a/test/foldable/minimal_foldable.hpp +++ b/test/foldable/minimal_foldable.hpp @@ -8,10 +8,49 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_HANA_TEST_FOLDABLE_MINIMAL_FOLDABLE_HPP #include -#include +#include -//! @todo Write a real minimal foldable. -BOOST_HANA_CONSTEXPR_LAMBDA auto foldable = boost::hana::list; +struct MinimalFoldable; + +template +struct _foldable { + Storage storage; + using hana_datatype = MinimalFoldable; +}; + +BOOST_HANA_CONSTEXPR_LAMBDA auto foldable = [](auto ...xs) { + auto storage = [=](auto f) { return f(xs...); }; + return _foldable{storage}; +}; + +namespace boost { namespace hana { + template <> + struct Foldable + : defaults::with + { + struct helper { + template + constexpr auto operator()(F f, S s, X x, Xs ...xs) const { + return f( + [=] { return x; }, + [=](auto ...nothing) { + static_assert(sizeof...(nothing) == 0, ""); + return lazy_foldr(f, s, foldable(xs..., nothing...)); + } + ); + } + + template + constexpr auto operator()(F f, S s) const + { return s; } + }; + + template + static constexpr auto lazy_foldr_impl(F f, S s, Xs xs) { + return xs.storage([=](auto ...xs) { return helper{}(f, s, xs...); }); + } + }; +}} #endif // !BOOST_HANA_TEST_FOLDABLE_MINIMAL_FOLDABLE_HPP diff --git a/test/foldable/minimum.cpp b/test/foldable/minimum.cpp index 110aad6f6..ebaa2e4af 100644 --- a/test/foldable/minimum.cpp +++ b/test/foldable/minimum.cpp @@ -14,7 +14,59 @@ using namespace boost::hana; int main() { + // compile-time BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, int_<1>)) == int_<0>); BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<0>)) == int_<0>); + + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, int_<1>, int_<2>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<0>, int_<2>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<2>, int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<2>, int_<1>, int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<2>, int_<0>, int_<1>)) == int_<0>); + + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, int_<1>, int_<2>, int_<3>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<0>, int_<2>, int_<3>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<2>, int_<0>, int_<3>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<1>, int_<2>, int_<3>, int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<2>, int_<1>, int_<3>, int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<2>, int_<3>, int_<1>, int_<0>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<2>, int_<3>, int_<0>, int_<1>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<3>, int_<2>, int_<0>, int_<1>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<3>, int_<0>, int_<2>, int_<1>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<3>, int_<0>, int_<1>, int_<2>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, int_<2>, int_<3>, int_<1>)) == int_<0>); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, int_<3>, int_<1>, int_<2>)) == int_<0>); + + + // constexpr/runtime + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0})) == int{0}); + + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{1})) == int{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{0})) == char{0}); + + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{1}, long{2})) == int{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{0}, long{2})) == char{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{2}, long{0})) == long{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{2}, char{1}, long{0})) == long{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{2}, char{0}, long{1})) == char{0}); + + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{1}, long{2}, double{3})) == int{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{0}, long{2}, double{3})) == char{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{2}, long{0}, double{3})) == long{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{1}, char{2}, long{3}, double{0})) == double{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{2}, char{1}, long{3}, double{0})) == double{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{2}, char{3}, long{1}, double{0})) == double{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{2}, char{3}, long{0}, double{1})) == long{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{3}, char{2}, long{0}, double{1})) == long{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{3}, char{0}, long{2}, double{1})) == char{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{3}, char{0}, long{1}, double{2})) == char{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{2}, long{3}, double{1})) == int{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{3}, long{1}, double{2})) == int{0}); + + + // mixed + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int{0}, char{1}, long_<2>)) == int{0}); + BOOST_HANA_STATIC_ASSERT(minimum(foldable(int_<0>, char{1}, long{2})) == int_<0>); } diff --git a/test/foldable/product.cpp b/test/foldable/product.cpp index 767e44fde..ee5d3bd7b 100644 --- a/test/foldable/product.cpp +++ b/test/foldable/product.cpp @@ -15,7 +15,13 @@ using namespace boost::hana; int main() { BOOST_HANA_STATIC_ASSERT(product(foldable()) == int_<1>); - BOOST_HANA_STATIC_ASSERT(product(foldable(int_<1>)) == int_<1>); - BOOST_HANA_STATIC_ASSERT(product(foldable(int_<1>, int_<2>)) == int_<2>); - BOOST_HANA_STATIC_ASSERT(product(foldable(int_<1>, int_<2>, int_<3>)) == int_<6>); + BOOST_HANA_STATIC_ASSERT(product(foldable(int_<2>)) == int_<2>); + BOOST_HANA_STATIC_ASSERT(product(foldable(int_<2>, int_<3>)) == int_<2 * 3>); + BOOST_HANA_STATIC_ASSERT(product(foldable(int_<2>, int_<3>, int_<4>)) == int_<2 * 3 * 4>); + BOOST_HANA_STATIC_ASSERT(product(foldable(int_<2>, int_<3>, int_<4>, int_<5>)) == int_<2 * 3 * 4 * 5>); + + BOOST_HANA_STATIC_ASSERT(product(foldable(2)) == 2); + BOOST_HANA_STATIC_ASSERT(product(foldable(2, 3)) == 2 * 3); + BOOST_HANA_STATIC_ASSERT(product(foldable(2, 3, 4)) == 2 * 3 * 4); + BOOST_HANA_STATIC_ASSERT(product(foldable(2, 3, 4, 5)) == 2 * 3 * 4 * 5); } diff --git a/test/foldable/sum.cpp b/test/foldable/sum.cpp index 0e101b339..0913f073b 100644 --- a/test/foldable/sum.cpp +++ b/test/foldable/sum.cpp @@ -15,7 +15,13 @@ using namespace boost::hana; int main() { BOOST_HANA_STATIC_ASSERT(sum(foldable()) == int_<0>); - BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<0>)) == int_<0>); - BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<0>, int_<1>)) == int_<1>); - BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<0>, int_<1>, int_<2>)) == int_<3>); + BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<1>)) == int_<1>); + BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<1>, int_<2>)) == int_<1 + 2>); + BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<1>, int_<2>, int_<3>)) == int_<1 + 2 + 3>); + BOOST_HANA_STATIC_ASSERT(sum(foldable(int_<1>, int_<2>, int_<3>, int_<4>)) == int_<1 + 2 + 3 + 4>); + + BOOST_HANA_STATIC_ASSERT(sum(foldable(1)) == 1); + BOOST_HANA_STATIC_ASSERT(sum(foldable(1, 2)) == 1 + 2); + BOOST_HANA_STATIC_ASSERT(sum(foldable(1, 2, 3)) == 1 + 2 + 3); + BOOST_HANA_STATIC_ASSERT(sum(foldable(1, 2, 3, 4)) == 1 + 2 + 3 + 4); } diff --git a/test/foldable/unpack.cpp b/test/foldable/unpack.cpp index 430e1fb0c..7e8912996 100644 --- a/test/foldable/unpack.cpp +++ b/test/foldable/unpack.cpp @@ -6,22 +6,27 @@ Distributed under the Boost Software License, Version 1.0. #include +#include #include -#include #include -#include #include "minimal_foldable.hpp" +#include using namespace boost::hana; -int main() { - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable()) == list()); - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(int_<0>)) == list_c); - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(int_<0>, int_<1>)) == list_c); - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(int_<0>, int_<1>, int_<2>)) == list_c); +BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto ...xs) { + return std::make_tuple(xs...); +}; - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(0)) == list(0)); - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(0, '1')) == list(0, '1')); - BOOST_HANA_STATIC_ASSERT(unpack(list, foldable(0, '1', "2")) == list(0, '1', "2")); +int main() { + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable()) == f()); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(1)) == f(1)); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(1, '2')) == f(1, '2')); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(1, '2', 3.3)) == f(1, '2', 3.3)); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(1, '2', 3.3, nullptr)) == f(1, '2', 3.3, nullptr)); + + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(int_<0>)) == f(int_<0>)); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(int_<0>, int_<1>)) == f(int_<0>, int_<1>)); + BOOST_HANA_STATIC_ASSERT(unpack(f, foldable(int_<0>, int_<1>, int_<2>)) == f(int_<0>, int_<1>, int_<2>)); } diff --git a/test/iterable/find.cpp b/test/iterable/find.cpp deleted file mode 100644 index 572f3cb1a..000000000 --- a/test/iterable/find.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* -@copyright Louis Dionne 2014 -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 "minimal_iterable.hpp" -using namespace boost::hana; - - -int main() { - BOOST_HANA_STATIC_ASSERT(find(always(true_), iterable()) == nothing); - - BOOST_HANA_STATIC_ASSERT(find(always(true_), iterable(int_<0>)) == just(int_<0>)); - BOOST_HANA_STATIC_ASSERT(find(always(false_), iterable(int_<0>)) == nothing); - - BOOST_HANA_STATIC_ASSERT(find(id, iterable(true_)) == just(true_)); - BOOST_HANA_STATIC_ASSERT(find(id, iterable(true_, false_)) == just(true_)); - BOOST_HANA_STATIC_ASSERT(find(id, iterable(false_, true_)) == just(true_)); - BOOST_HANA_STATIC_ASSERT(find(id, iterable(false_, false_)) == nothing); -} diff --git a/test/iterable/foldable.cpp b/test/iterable/foldable.cpp index a3f317e5b..c3d27b784 100644 --- a/test/iterable/foldable.cpp +++ b/test/iterable/foldable.cpp @@ -11,6 +11,7 @@ Distributed under the Boost Software License, Version 1.0. #include #include #include +#include #include "minimal_iterable.hpp" using namespace boost::hana; @@ -53,10 +54,23 @@ void test_lazy_foldr() { BOOST_HANA_STATIC_ASSERT(lazy_foldr(strict_list, int_<3>, iterable(int_<0>, int_<1>, int_<2>)) == list(int_<0>, list(int_<1>, list(int_<2>, int_<3>)))); } +void test_find() { + BOOST_HANA_STATIC_ASSERT(find(always(true_), iterable()) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(always(true_), iterable(int_<0>)) == just(int_<0>)); + BOOST_HANA_STATIC_ASSERT(find(always(false_), iterable(int_<0>)) == nothing); + + BOOST_HANA_STATIC_ASSERT(find(id, iterable(true_)) == just(true_)); + BOOST_HANA_STATIC_ASSERT(find(id, iterable(true_, false_)) == just(true_)); + BOOST_HANA_STATIC_ASSERT(find(id, iterable(false_, true_)) == just(true_)); + BOOST_HANA_STATIC_ASSERT(find(id, iterable(false_, false_)) == nothing); +} + int main() { test_foldl(); test_foldl1(); test_foldr(); test_foldr1(); test_lazy_foldr(); + test_find(); }