Line data Source code
1 : /*!
2 : @file
3 : Defines `boost::hana::unpack`.
4 :
5 : Copyright Louis Dionne 2013-2022
6 : Distributed under the Boost Software License, Version 1.0.
7 : (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 : */
9 :
10 : #ifndef BOOST_HANA_UNPACK_HPP
11 : #define BOOST_HANA_UNPACK_HPP
12 :
13 : #include <boost/hana/fwd/unpack.hpp>
14 :
15 : #include <boost/hana/accessors.hpp>
16 : #include <boost/hana/at.hpp>
17 : #include <boost/hana/concept/foldable.hpp>
18 : #include <boost/hana/concept/iterable.hpp>
19 : #include <boost/hana/concept/struct.hpp>
20 : #include <boost/hana/config.hpp>
21 : #include <boost/hana/core/dispatch.hpp>
22 : #include <boost/hana/first.hpp>
23 : #include <boost/hana/functional/partial.hpp>
24 : #include <boost/hana/fwd/fold_left.hpp>
25 : #include <boost/hana/length.hpp>
26 : #include <boost/hana/pair.hpp>
27 : #include <boost/hana/second.hpp>
28 :
29 : #include <cstddef>
30 : #include <utility>
31 :
32 :
33 : namespace boost { namespace hana {
34 : //! @cond
35 : template <typename Xs, typename F>
36 1967890 : constexpr decltype(auto) unpack_t::operator()(Xs&& xs, F&& f) const {
37 : using S = typename hana::tag_of<Xs>::type;
38 : using Unpack = BOOST_HANA_DISPATCH_IF(unpack_impl<S>,
39 : hana::Foldable<S>::value
40 : );
41 :
42 : #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
43 : static_assert(hana::Foldable<S>::value,
44 : "hana::unpack(xs, f) requires 'xs' to be Foldable");
45 : #endif
46 :
47 1967890 : return Unpack::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
48 : }
49 : //! @endcond
50 :
51 : template <typename T, bool condition>
52 : struct unpack_impl<T, when<condition>> : default_ {
53 : template <typename Xs, typename F>
54 : static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
55 : return hana::fold_left(static_cast<Xs&&>(xs),
56 : static_cast<F&&>(f),
57 : hana::partial)();
58 : }
59 : };
60 :
61 : template <typename It>
62 : struct unpack_impl<It, when<
63 : hana::Iterable<It>::value && !is_default<length_impl<It>>::value
64 : >> {
65 : template <typename Xs, typename F, std::size_t ...i>
66 : static constexpr decltype(auto)
67 : unpack_helper(Xs&& xs, F&& f, std::index_sequence<i...>) {
68 : return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs))...);
69 : }
70 :
71 : template <typename Xs, typename F>
72 : static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
73 : constexpr std::size_t N = decltype(hana::length(xs))::value;
74 : return unpack_helper(static_cast<Xs&&>(xs), static_cast<F&&>(f),
75 : std::make_index_sequence<N>{});
76 : }
77 : };
78 :
79 : template <typename T, std::size_t N>
80 : struct unpack_impl<T[N]> {
81 : template <typename Xs, typename F, std::size_t ...i>
82 : static constexpr decltype(auto)
83 : unpack_helper(Xs&& xs, F&& f, std::index_sequence<i...>) {
84 : return static_cast<F&&>(f)(static_cast<Xs&&>(xs)[i]...);
85 : }
86 :
87 : template <typename Xs, typename F>
88 : static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
89 : return unpack_impl::unpack_helper(static_cast<Xs&&>(xs),
90 : static_cast<F&&>(f),
91 : std::make_index_sequence<N>{});
92 : }
93 : };
94 :
95 : //////////////////////////////////////////////////////////////////////////
96 : // Model for Products
97 : //////////////////////////////////////////////////////////////////////////
98 : template <typename T>
99 : struct unpack_impl<T, when<hana::Product<T>::value>> {
100 : template <typename P, typename F>
101 : static constexpr decltype(auto) apply(P&& p, F&& f) {
102 : return static_cast<F&&>(f)(
103 : hana::first(static_cast<P&&>(p)),
104 : hana::second(static_cast<P&&>(p))
105 : );
106 : }
107 : };
108 :
109 : //////////////////////////////////////////////////////////////////////////
110 : // Model for Structs
111 : //////////////////////////////////////////////////////////////////////////
112 : namespace struct_detail {
113 : // This is equivalent to `demux`, except that `demux` can't forward
114 : // the `udt` because it does not know the `g`s are accessors. Hence,
115 : // this can result in faster code.
116 : struct almost_demux {
117 : template <typename F, typename Udt, typename ...Members>
118 : constexpr decltype(auto)
119 : operator()(F&& f, Udt&& udt, Members&& ...g) const {
120 : return static_cast<F&&>(f)(hana::make_pair(
121 : hana::first(static_cast<Members&&>(g)),
122 : hana::second(static_cast<Members&&>(g))
123 : (static_cast<Udt&&>(udt))
124 : )...);
125 : }
126 : };
127 : }
128 :
129 : template <typename S>
130 : struct unpack_impl<S, when<hana::Struct<S>::value>> {
131 : template <typename Udt, typename F>
132 : static constexpr decltype(auto) apply(Udt&& udt, F&& f) {
133 : return hana::unpack(hana::accessors<S>(),
134 : hana::partial(struct_detail::almost_demux{},
135 : static_cast<F&&>(f),
136 : static_cast<Udt&&>(udt)));
137 : }
138 : };
139 : }} // end namespace boost::hana
140 :
141 : #endif // !BOOST_HANA_UNPACK_HPP
|