Line data Source code
1 : /*!
2 : @file
3 : Defines `boost::hana::basic_tuple`.
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_BASIC_TUPLE_HPP
11 : #define BOOST_HANA_BASIC_TUPLE_HPP
12 :
13 : #include <boost/hana/fwd/basic_tuple.hpp>
14 :
15 : #include <boost/hana/config.hpp>
16 : #include <boost/hana/detail/decay.hpp>
17 : #include <boost/hana/detail/ebo.hpp>
18 : #include <boost/hana/fwd/at.hpp>
19 : #include <boost/hana/fwd/bool.hpp>
20 : #include <boost/hana/fwd/concept/sequence.hpp>
21 : #include <boost/hana/fwd/core/make.hpp>
22 : #include <boost/hana/fwd/core/tag_of.hpp>
23 : #include <boost/hana/fwd/drop_front.hpp>
24 : #include <boost/hana/fwd/integral_constant.hpp>
25 : #include <boost/hana/fwd/is_empty.hpp>
26 : #include <boost/hana/fwd/length.hpp>
27 : #include <boost/hana/fwd/transform.hpp>
28 : #include <boost/hana/fwd/unpack.hpp>
29 :
30 : #include <cstddef>
31 : #include <type_traits>
32 : #include <utility>
33 :
34 :
35 : namespace boost { namespace hana {
36 : namespace detail {
37 : //////////////////////////////////////////////////////////////////////
38 : // basic_tuple_impl<n, Xn>
39 : //////////////////////////////////////////////////////////////////////
40 : template <std::size_t> struct bti; // basic_tuple_index
41 :
42 : struct from_other { };
43 :
44 : template <typename Indices, typename ...Xn>
45 : #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
46 : struct __declspec(empty_bases) basic_tuple_impl;
47 : #else
48 : struct basic_tuple_impl;
49 : #endif
50 :
51 : template <std::size_t ...n, typename ...Xn>
52 : #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
53 : struct __declspec(empty_bases) basic_tuple_impl<std::index_sequence<n...>, Xn...>
54 : #else
55 : struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
56 : #endif
57 : : detail::ebo<bti<n>, Xn>...
58 : {
59 : static constexpr std::size_t size_ = sizeof...(Xn);
60 :
61 : constexpr basic_tuple_impl() = default;
62 :
63 : template <typename Other>
64 : explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
65 : : detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))...
66 : { }
67 :
68 : template <typename ...Yn>
69 : explicit constexpr basic_tuple_impl(Yn&& ...yn)
70 : : detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))...
71 : { }
72 : };
73 : }
74 :
75 : //////////////////////////////////////////////////////////////////////////
76 : // basic_tuple
77 : //////////////////////////////////////////////////////////////////////////
78 : //! @cond
79 : template <typename ...Xn>
80 : struct basic_tuple final
81 : : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
82 : {
83 : using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
84 :
85 : constexpr basic_tuple() = default;
86 :
87 : // copy constructor
88 : template <typename Other, typename = typename std::enable_if<
89 : std::is_same<typename detail::decay<Other>::type, basic_tuple>::value
90 : >::type>
91 : constexpr basic_tuple(Other&& other)
92 : : Base(detail::from_other{}, static_cast<Other&&>(other))
93 : { }
94 :
95 : template <typename ...Yn>
96 : explicit constexpr basic_tuple(Yn&& ...yn)
97 : : Base(static_cast<Yn&&>(yn)...)
98 : { }
99 : };
100 : //! @endcond
101 :
102 : template <typename ...Xn>
103 : struct tag_of<basic_tuple<Xn...>> {
104 : using type = basic_tuple_tag;
105 : };
106 :
107 : //////////////////////////////////////////////////////////////////////////
108 : // Foldable
109 : //////////////////////////////////////////////////////////////////////////
110 : template <>
111 : struct unpack_impl<basic_tuple_tag> {
112 : template <std::size_t ...i, typename ...Xn, typename F>
113 : static constexpr decltype(auto)
114 983945 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
115 1967890 : return static_cast<F&&>(f)(
116 18694955 : detail::ebo_get<detail::bti<i>>(
117 18694955 : static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
118 : )...
119 : );
120 : }
121 :
122 : template <std::size_t ...i, typename ...Xn, typename F>
123 : static constexpr decltype(auto)
124 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
125 : return static_cast<F&&>(f)(
126 : detail::ebo_get<detail::bti<i>>(
127 : static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
128 : )...
129 : );
130 : }
131 :
132 : template <std::size_t ...i, typename ...Xn, typename F>
133 : static constexpr decltype(auto)
134 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
135 : return static_cast<F&&>(f)(
136 : detail::ebo_get<detail::bti<i>>(
137 : static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
138 : )...
139 : );
140 : }
141 : };
142 :
143 : //////////////////////////////////////////////////////////////////////////
144 : // Functor
145 : //////////////////////////////////////////////////////////////////////////
146 : template <>
147 : struct transform_impl<basic_tuple_tag> {
148 : template <std::size_t ...i, typename ...Xn, typename F>
149 : static constexpr auto
150 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
151 : return hana::make_basic_tuple(
152 : f(detail::ebo_get<detail::bti<i>>(
153 : static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
154 : ))...
155 : );
156 : }
157 :
158 : template <std::size_t ...i, typename ...Xn, typename F>
159 : static constexpr auto
160 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
161 : return hana::make_basic_tuple(
162 : f(detail::ebo_get<detail::bti<i>>(
163 : static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
164 : ))...
165 : );
166 : }
167 :
168 : template <std::size_t ...i, typename ...Xn, typename F>
169 : static constexpr auto
170 : apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
171 : return hana::make_basic_tuple(
172 : f(detail::ebo_get<detail::bti<i>>(
173 : static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
174 : ))...
175 : );
176 : }
177 : };
178 :
179 : //////////////////////////////////////////////////////////////////////////
180 : // Iterable
181 : //////////////////////////////////////////////////////////////////////////
182 : template <>
183 : struct at_impl<basic_tuple_tag> {
184 : template <typename Xs, typename N>
185 : static constexpr decltype(auto) apply(Xs&& xs, N const&) {
186 : constexpr std::size_t index = N::value;
187 : return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs));
188 : }
189 : };
190 :
191 : template <>
192 : struct drop_front_impl<basic_tuple_tag> {
193 : template <std::size_t N, typename Xs, std::size_t ...i>
194 : static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
195 : return hana::make_basic_tuple(
196 : detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))...
197 : );
198 : }
199 :
200 : template <typename Xs, typename N>
201 : static constexpr auto apply(Xs&& xs, N const&) {
202 : constexpr std::size_t len = detail::decay<Xs>::type::size_;
203 : return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
204 : (N::value < len) ? len - N::value : 0
205 : >{});
206 : }
207 : };
208 :
209 : template <>
210 : struct is_empty_impl<basic_tuple_tag> {
211 : template <typename ...Xs>
212 : static constexpr hana::bool_<sizeof...(Xs) == 0>
213 : apply(basic_tuple<Xs...> const&)
214 : { return {}; }
215 : };
216 :
217 : // compile-time optimizations (to reduce the # of function instantiations)
218 : template <std::size_t n, typename ...Xs>
219 : constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) {
220 : return detail::ebo_get<detail::bti<n>>(xs);
221 : }
222 :
223 : template <std::size_t n, typename ...Xs>
224 : constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) {
225 : return detail::ebo_get<detail::bti<n>>(xs);
226 : }
227 :
228 : template <std::size_t n, typename ...Xs>
229 : constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) {
230 : return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs));
231 : }
232 :
233 : //////////////////////////////////////////////////////////////////////////
234 : // Sequence
235 : //////////////////////////////////////////////////////////////////////////
236 : template <>
237 : struct Sequence<basic_tuple_tag> {
238 : static constexpr bool value = true;
239 : };
240 :
241 : template <>
242 : struct make_impl<basic_tuple_tag> {
243 : template <typename ...Xn>
244 : static constexpr basic_tuple<typename detail::decay<Xn>::type...>
245 : apply(Xn&& ...xn) {
246 : return basic_tuple<typename detail::decay<Xn>::type...>{
247 : static_cast<Xn&&>(xn)...
248 : };
249 : }
250 : };
251 :
252 : //////////////////////////////////////////////////////////////////////////
253 : // length
254 : //////////////////////////////////////////////////////////////////////////
255 : template <>
256 : struct length_impl<basic_tuple_tag> {
257 : template <typename ...Xn>
258 : static constexpr auto apply(basic_tuple<Xn...> const&) {
259 : return hana::size_t<sizeof...(Xn)>{};
260 : }
261 : };
262 : }} // end namespace boost::hana
263 :
264 : #endif // !BOOST_HANA_BASIC_TUPLE_HPP
|