// 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, ""); }