/*! @file Defines `boost::hana::unpack`. @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) */ #ifndef BOOST_HANA_UNPACK_HPP #define BOOST_HANA_UNPACK_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace hana { //! @cond template constexpr decltype(auto) unpack_t::operator()(Xs&& xs, F&& f) const { using S = typename hana::tag_of::type; using Unpack = BOOST_HANA_DISPATCH_IF(unpack_impl, hana::Foldable::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Foldable::value, "hana::unpack(xs, f) requires 'xs' to be Foldable"); #endif return Unpack::apply(static_cast(xs), static_cast(f)); } //! @endcond template struct unpack_impl> : default_ { template static constexpr decltype(auto) apply(Xs&& xs, F&& f) { return hana::fold_left(static_cast(xs), static_cast(f), hana::partial)(); } }; template struct unpack_impl::value && !is_default>::value >> { template static constexpr decltype(auto) unpack_helper(Xs&& xs, F&& f, std::index_sequence) { return static_cast(f)(hana::at_c(static_cast(xs))...); } template static constexpr decltype(auto) apply(Xs&& xs, F&& f) { constexpr std::size_t N = decltype(hana::length(xs))::value; return unpack_helper(static_cast(xs), static_cast(f), std::make_index_sequence{}); } }; template struct unpack_impl { template static constexpr decltype(auto) unpack_helper(Xs&& xs, F&& f, std::index_sequence) { return static_cast(f)(static_cast(xs)[i]...); } template static constexpr decltype(auto) apply(Xs&& xs, F&& f) { return unpack_impl::unpack_helper(static_cast(xs), static_cast(f), std::make_index_sequence{}); } }; ////////////////////////////////////////////////////////////////////////// // Model for Products ////////////////////////////////////////////////////////////////////////// template struct unpack_impl::value>> { template static constexpr decltype(auto) apply(P&& p, F&& f) { return static_cast(f)( hana::first(static_cast(p)), hana::second(static_cast(p)) ); } }; ////////////////////////////////////////////////////////////////////////// // Model for Structs ////////////////////////////////////////////////////////////////////////// namespace struct_detail { // This is equivalent to `demux`, except that `demux` can't forward // the `udt` because it does not know the `g`s are accessors. Hence, // this can result in faster code. struct almost_demux { template constexpr decltype(auto) operator()(F&& f, Udt&& udt, Members&& ...g) const { return static_cast(f)(hana::make_pair( hana::first(static_cast(g)), hana::second(static_cast(g)) (static_cast(udt)) )...); } }; } template struct unpack_impl::value>> { template static constexpr decltype(auto) apply(Udt&& udt, F&& f) { return hana::unpack(hana::accessors(), hana::partial(struct_detail::almost_demux{}, static_cast(f), static_cast(udt))); } }; }} // end namespace boost::hana #endif // !BOOST_HANA_UNPACK_HPP