123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- // Copyright Louis Dionne 2013-2017
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- #include <boost/hana/assert.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/functional.hpp>
- #include <laws/base.hpp>
- #include <support/tracked.hpp>
- #include <utility>
- namespace hana = boost::hana;
- template <int i = 0>
- struct nonpod : Tracked {
- nonpod() : Tracked{i} { }
- };
- template <int i = 0>
- struct undefined { };
- struct move_only {
- move_only() = default;
- move_only(move_only&&) = default;
- move_only(move_only const&) = delete;
- };
- int main() {
- hana::test::_injection<0> f{};
- hana::test::_injection<1> g{};
- hana::test::_injection<2> h{};
- using hana::test::ct_eq;
- // always
- {
- auto z = ct_eq<0>{};
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::always(z)(), z
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::always(z)(undefined<1>{}), z
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::always(z)(undefined<1>{}, undefined<2>{}), z
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::always(z)(undefined<1>{}, undefined<2>{}, undefined<3>{}), z
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::always(z)(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}), z
- ));
- hana::always(z)(nonpod<>{});
- auto m = hana::always(move_only{})(undefined<1>{}); (void)m;
- }
- // apply (tested separately)
- {
- }
- // arg
- {
- // moveonly friendliness:
- move_only z = hana::arg<1>(move_only{}); (void)z;
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<1>(ct_eq<1>{}),
- ct_eq<1>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<1>(ct_eq<1>{}, undefined<2>{}),
- ct_eq<1>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<1>(ct_eq<1>{}, undefined<2>{}, undefined<3>{}),
- ct_eq<1>{}
- ));
- hana::arg<1>(nonpod<1>{});
- hana::arg<1>(nonpod<1>{}, nonpod<2>{});
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<2>(undefined<1>{}, ct_eq<2>{}),
- ct_eq<2>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<2>(undefined<1>{}, ct_eq<2>{}, undefined<3>{}),
- ct_eq<2>{}
- ));
- hana::arg<2>(nonpod<1>{}, nonpod<2>{});
- hana::arg<2>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{});
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<3>(undefined<1>{}, undefined<2>{}, ct_eq<3>{}),
- ct_eq<3>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<3>(undefined<1>{}, undefined<2>{}, ct_eq<3>{}, undefined<4>{}),
- ct_eq<3>{}
- ));
- hana::arg<3>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{});
- hana::arg<3>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{});
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<4>(undefined<1>{}, undefined<2>{}, undefined<3>{}, ct_eq<4>{}),
- ct_eq<4>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<4>(undefined<1>{}, undefined<2>{}, undefined<3>{}, ct_eq<4>{}, undefined<5>{}),
- ct_eq<4>{}
- ));
- hana::arg<4>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{});
- hana::arg<4>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{});
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<5>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, ct_eq<5>{}),
- ct_eq<5>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<5>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, ct_eq<5>{}, undefined<6>{}),
- ct_eq<5>{}
- ));
- hana::arg<5>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{});
- hana::arg<5>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{});
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<6>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, undefined<5>{}, ct_eq<6>{}),
- ct_eq<6>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::arg<6>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, undefined<5>{}, ct_eq<6>{}, undefined<7>{}),
- ct_eq<6>{}
- ));
- hana::arg<6>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{});
- hana::arg<6>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{}, nonpod<7>{});
- }
- // compose
- {
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g)(ct_eq<0>{}),
- f(g(ct_eq<0>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g)(ct_eq<0>{}, ct_eq<1>{}),
- f(g(ct_eq<0>{}), ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(g(ct_eq<0>{}), ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g, h)(ct_eq<0>{}),
- f(g(h(ct_eq<0>{})))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g, h)(ct_eq<0>{}, ct_eq<1>{}),
- f(g(h(ct_eq<0>{})), ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::compose(f, g, h)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(g(h(ct_eq<0>{})), ct_eq<1>{}, ct_eq<2>{})
- ));
- auto h = [capture = move_only{}](int) { (void)capture; return 1; };
- auto i = [](int) { return 1; };
- hana::compose(std::move(h), i)(1);
- {
- // Compose move-only functions.
- auto f = [capture = move_only{}](int) { (void)capture; return 1; };
- auto g = [capture = move_only{}](int) { (void)capture; return 1; };
- auto c = hana::compose(std::move(f), std::move(g)); (void)c;
- }
- }
- // curry
- {
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<0>(f)(),
- f()
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<1>(f)(ct_eq<1>{}),
- f(ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<2>(f)(ct_eq<1>{})(ct_eq<2>{}),
- f(ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<2>(f)(ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(f)(ct_eq<1>{})(ct_eq<2>{})(ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(f)(ct_eq<1>{})(ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(f)(ct_eq<1>{}, ct_eq<2>{})(ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- // Make sure curry is idempotent; this is important because it allows
- // currying a function in generic contexts where it is unknown whether
- // the function is already curried.
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<0>(hana::curry<0>(f))(),
- f()
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<1>(hana::curry<1>(f))(ct_eq<1>{}),
- f(ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<2>(hana::curry<2>(f))(ct_eq<1>{})(ct_eq<2>{}),
- f(ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<2>(hana::curry<2>(f))(ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{})(ct_eq<2>{})(ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{})(ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{}, ct_eq<2>{})(ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- }
- // demux (tested separately)
- {
- }
- // fix (tested separately)
- {
- }
- // flip
- {
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<2>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
- f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<4>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}),
- f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{})
- ));
- }
- // id
- {
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::id(ct_eq<0>{}),
- ct_eq<0>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::id(ct_eq<1>{}),
- ct_eq<1>{}
- ));
- (void)hana::id(move_only{});
- // make sure we don't return a dangling reference
- auto f = []() -> decltype(auto) { return hana::id(Tracked{1}); };
- auto z = f(); (void)z;
- }
- // lockstep (tested separately)
- {
- }
- // infix
- {
- auto g = hana::infix(f);
- // disregard associativity
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- ct_eq<0>{} ^g^ ct_eq<1>{},
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (ct_eq<0>{} ^g)^ ct_eq<1>{},
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- ct_eq<0>{} ^(g^ ct_eq<1>{}),
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- // left partial application
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (ct_eq<0>{}^g)(ct_eq<1>{}),
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (ct_eq<0>{}^g)(ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (ct_eq<0>{}^g)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- // right partial application
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (g^ct_eq<1>{})(ct_eq<0>{}),
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (g^ct_eq<2>{})(ct_eq<0>{}, ct_eq<1>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (g^ct_eq<3>{})(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- // equivalence with the base function
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- g(ct_eq<0>{}, ct_eq<1>{}),
- f(ct_eq<0>{}, ct_eq<1>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- g(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- g(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
- ));
- }
- // on
- {
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::on(f, g)(),
- f()
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::on(f, g)(ct_eq<0>{}),
- f(g(ct_eq<0>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}), g(ct_eq<3>{}))
- ));
- // check the infix version
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (f ^hana::on^ g)(),
- f()
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (f ^hana::on^ g)(ct_eq<0>{}),
- f(g(ct_eq<0>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
- f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}), g(ct_eq<3>{}))
- ));
- }
- // overload
- {
- // 1 function
- {
- auto f = hana::overload([](int) { return ct_eq<1>{}; });
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
- }
- // 2 functions
- {
- auto f = hana::overload(
- [](int) { return ct_eq<1>{}; },
- [](float) { return ct_eq<2>{}; }
- );
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
- }
- // 3 functions
- {
- auto f = hana::overload(
- [](int) { return ct_eq<1>{}; },
- [](float) { return ct_eq<2>{}; },
- static_cast<ct_eq<3>(*)(char)>([](char) { return ct_eq<3>{}; })
- );
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(char{}), ct_eq<3>{}));
- }
- // 4 functions
- {
- auto f = hana::overload(
- [](int) { return ct_eq<1>{}; },
- [](float) { return ct_eq<2>{}; },
- static_cast<ct_eq<3>(*)(char)>([](char) { return ct_eq<3>{}; }),
- [](auto) { return ct_eq<4>{}; }
- );
- struct otherwise { };
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(char{}), ct_eq<3>{}));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(f(otherwise{}), ct_eq<4>{}));
- }
- // check move-only friendliness for bare functions
- {
- void (*g)(move_only) = [](move_only) { };
- hana::overload(g)(move_only{});
- }
- // check non-strict matches which require a conversion
- {
- struct convertible_to_int { operator int() const { return 1; } };
- auto f = [](int) { return ct_eq<0>{}; };
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::overload(f)(convertible_to_int{}),
- ct_eq<0>{}
- ));
- BOOST_HANA_CONSTANT_CHECK(hana::equal(
- hana::overload(static_cast<ct_eq<0>(*)(int)>(f))(convertible_to_int{}),
- ct_eq<0>{}
- ));
- }
- }
- // partial (tested separately)
- {
- }
- // placeholder (tested separately)
- {
- }
- }
|