]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Defines `boost::hana::basic_tuple`. | |
4 | ||
5 | @copyright Louis Dionne 2013-2016 | |
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/intrinsics.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/is_empty.hpp> | |
25 | #include <boost/hana/fwd/transform.hpp> | |
26 | #include <boost/hana/fwd/unpack.hpp> | |
27 | ||
28 | #if 0 //! @todo Until we strip down headers, this includes too much | |
29 | #include <boost/hana/fwd/integral_constant.hpp> | |
30 | #include <boost/hana/fwd/length.hpp> | |
31 | #endif | |
32 | ||
33 | #include <cstddef> | |
34 | #include <type_traits> | |
35 | #include <utility> | |
36 | ||
37 | ||
38 | BOOST_HANA_NAMESPACE_BEGIN | |
39 | namespace detail { | |
40 | ////////////////////////////////////////////////////////////////////// | |
41 | // elt<n, Xn> | |
42 | // | |
43 | // `elt` stands for `tuple_element`; the name is compressed to reduce | |
44 | // symbol lengths. | |
45 | // | |
46 | // Wrapper holding the actual elements of a tuple. It takes care of | |
47 | // optimizing the storage for empty types. | |
48 | // | |
49 | // When available, we use compiler intrinsics to reduce the number | |
50 | // of instantiations. | |
51 | ////////////////////////////////////////////////////////////////////// | |
52 | template <std::size_t n, typename Xn, bool = | |
53 | BOOST_HANA_TT_IS_EMPTY(Xn) && !BOOST_HANA_TT_IS_FINAL(Xn) | |
54 | > | |
55 | struct elt; | |
56 | ||
57 | // Specialize storage for empty types | |
58 | template <std::size_t n, typename Xn> | |
59 | struct elt<n, Xn, true> : Xn { | |
60 | constexpr elt() = default; | |
61 | ||
62 | template <typename Yn> | |
63 | explicit constexpr elt(Yn&& yn) | |
64 | : Xn(static_cast<Yn&&>(yn)) | |
65 | { } | |
66 | }; | |
67 | ||
68 | // Specialize storage for non-empty types | |
69 | template <std::size_t n, typename Xn> | |
70 | struct elt<n, Xn, false> { | |
71 | constexpr elt() = default; | |
72 | ||
73 | template <typename Yn> | |
74 | explicit constexpr elt(Yn&& yn) | |
75 | : data_(static_cast<Yn&&>(yn)) | |
76 | { } | |
77 | ||
78 | Xn data_; | |
79 | }; | |
80 | } | |
81 | ||
82 | ////////////////////////////////////////////////////////////////////////// | |
83 | // get_impl | |
84 | ////////////////////////////////////////////////////////////////////////// | |
85 | template <std::size_t n, typename Xn> | |
86 | constexpr Xn const& get_impl(detail::elt<n, Xn, true> const& xn) | |
87 | { return xn; } | |
88 | ||
89 | template <std::size_t n, typename Xn> | |
90 | constexpr Xn& get_impl(detail::elt<n, Xn, true>& xn) | |
91 | { return xn; } | |
92 | ||
93 | template <std::size_t n, typename Xn> | |
94 | constexpr Xn&& get_impl(detail::elt<n, Xn, true>&& xn) | |
95 | { return static_cast<Xn&&>(xn); } | |
96 | ||
97 | ||
98 | template <std::size_t n, typename Xn> | |
99 | constexpr Xn const& get_impl(detail::elt<n, Xn, false> const& xn) | |
100 | { return xn.data_; } | |
101 | ||
102 | template <std::size_t n, typename Xn> | |
103 | constexpr Xn& get_impl(detail::elt<n, Xn, false>& xn) | |
104 | { return xn.data_; } | |
105 | ||
106 | template <std::size_t n, typename Xn> | |
107 | constexpr Xn&& get_impl(detail::elt<n, Xn, false>&& xn) | |
108 | { return static_cast<Xn&&>(xn.data_); } | |
109 | ||
110 | namespace detail { | |
111 | ////////////////////////////////////////////////////////////////////// | |
112 | // basic_tuple_impl<n, Xn> | |
113 | ////////////////////////////////////////////////////////////////////// | |
114 | struct from_other { }; | |
115 | ||
116 | template <typename Indices, typename ...Xn> | |
117 | struct basic_tuple_impl; | |
118 | ||
119 | template <std::size_t ...n, typename ...Xn> | |
120 | struct basic_tuple_impl<std::index_sequence<n...>, Xn...> | |
121 | : detail::elt<n, Xn>... | |
122 | { | |
123 | static constexpr std::size_t size_ = sizeof...(Xn); | |
124 | ||
125 | constexpr basic_tuple_impl() = default; | |
126 | ||
127 | template <typename Other> | |
128 | explicit constexpr basic_tuple_impl(detail::from_other, Other&& other) | |
129 | : detail::elt<n, Xn>(get_impl<n>(static_cast<Other&&>(other)))... | |
130 | { } | |
131 | ||
132 | template <typename ...Yn> | |
133 | explicit constexpr basic_tuple_impl(Yn&& ...yn) | |
134 | : detail::elt<n, Xn>(static_cast<Yn&&>(yn))... | |
135 | { } | |
136 | }; | |
137 | } | |
138 | ||
139 | ////////////////////////////////////////////////////////////////////////// | |
140 | // basic_tuple | |
141 | ////////////////////////////////////////////////////////////////////////// | |
142 | //! @cond | |
143 | template <typename ...Xn> | |
144 | struct basic_tuple final | |
145 | : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...> | |
146 | { | |
147 | using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>; | |
148 | ||
149 | constexpr basic_tuple() = default; | |
150 | ||
151 | // copy constructor | |
152 | template <typename Other, typename = typename std::enable_if< | |
153 | std::is_same<typename detail::decay<Other>::type, basic_tuple>::value | |
154 | >::type> | |
155 | constexpr basic_tuple(Other&& other) | |
156 | : Base(detail::from_other{}, static_cast<Other&&>(other)) | |
157 | { } | |
158 | ||
159 | template <typename ...Yn> | |
160 | explicit constexpr basic_tuple(Yn&& ...yn) | |
161 | : Base(static_cast<Yn&&>(yn)...) | |
162 | { } | |
163 | }; | |
164 | //! @endcond | |
165 | ||
166 | template <typename ...Xn> | |
167 | struct tag_of<basic_tuple<Xn...>> { | |
168 | using type = basic_tuple_tag; | |
169 | }; | |
170 | ||
171 | ////////////////////////////////////////////////////////////////////////// | |
172 | // Foldable | |
173 | ////////////////////////////////////////////////////////////////////////// | |
174 | template <> | |
175 | struct unpack_impl<basic_tuple_tag> { | |
176 | template <std::size_t ...i, typename ...Xn, typename F> | |
177 | static constexpr decltype(auto) | |
178 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) { | |
179 | return static_cast<F&&>(f)( | |
180 | get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs))... | |
181 | ); | |
182 | } | |
183 | ||
184 | template <std::size_t ...i, typename ...Xn, typename F> | |
185 | static constexpr decltype(auto) | |
186 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) { | |
187 | return static_cast<F&&>(f)( | |
188 | get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs))... | |
189 | ); | |
190 | } | |
191 | ||
192 | template <std::size_t ...i, typename ...Xn, typename F> | |
193 | static constexpr decltype(auto) | |
194 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) { | |
195 | return static_cast<F&&>(f)( | |
196 | get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs))... | |
197 | ); | |
198 | } | |
199 | }; | |
200 | ||
201 | ////////////////////////////////////////////////////////////////////////// | |
202 | // Functor | |
203 | ////////////////////////////////////////////////////////////////////////// | |
204 | template <> | |
205 | struct transform_impl<basic_tuple_tag> { | |
206 | template <std::size_t ...i, typename ...Xn, typename F> | |
207 | static constexpr auto | |
208 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) { | |
209 | return hana::make_basic_tuple( | |
210 | f(get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs)))... | |
211 | ); | |
212 | } | |
213 | ||
214 | template <std::size_t ...i, typename ...Xn, typename F> | |
215 | static constexpr auto | |
216 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) { | |
217 | return hana::make_basic_tuple( | |
218 | f(get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs)))... | |
219 | ); | |
220 | } | |
221 | ||
222 | template <std::size_t ...i, typename ...Xn, typename F> | |
223 | static constexpr auto | |
224 | apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) { | |
225 | return hana::make_basic_tuple( | |
226 | f(get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs)))... | |
227 | ); | |
228 | } | |
229 | }; | |
230 | ||
231 | ////////////////////////////////////////////////////////////////////////// | |
232 | // Iterable | |
233 | ////////////////////////////////////////////////////////////////////////// | |
234 | template <> | |
235 | struct at_impl<basic_tuple_tag> { | |
236 | template <typename Xs, typename N> | |
237 | static constexpr decltype(auto) apply(Xs&& xs, N const&) { | |
238 | constexpr std::size_t index = N::value; | |
239 | return hana::get_impl<index>(static_cast<Xs&&>(xs)); | |
240 | } | |
241 | }; | |
242 | ||
243 | template <> | |
244 | struct drop_front_impl<basic_tuple_tag> { | |
245 | template <std::size_t N, typename Xs, std::size_t ...i> | |
246 | static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) { | |
247 | return hana::make_basic_tuple(hana::get_impl<i+N>(static_cast<Xs&&>(xs))...); | |
248 | } | |
249 | ||
250 | template <typename Xs, typename N> | |
251 | static constexpr auto apply(Xs&& xs, N const&) { | |
252 | constexpr std::size_t len = detail::decay<Xs>::type::size_; | |
253 | return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence< | |
254 | N::value < len ? len - N::value : 0 | |
255 | >{}); | |
256 | } | |
257 | }; | |
258 | ||
259 | template <> | |
260 | struct is_empty_impl<basic_tuple_tag> { | |
261 | template <typename ...Xs> | |
262 | static constexpr hana::bool_<sizeof...(Xs) == 0> | |
263 | apply(basic_tuple<Xs...> const&) | |
264 | { return {}; } | |
265 | }; | |
266 | ||
267 | ////////////////////////////////////////////////////////////////////////// | |
268 | // Sequence | |
269 | ////////////////////////////////////////////////////////////////////////// | |
270 | template <> | |
271 | struct Sequence<basic_tuple_tag> { | |
272 | static constexpr bool value = true; | |
273 | }; | |
274 | ||
275 | template <> | |
276 | struct make_impl<basic_tuple_tag> { | |
277 | template <typename ...Xn> | |
278 | static constexpr basic_tuple<typename detail::decay<Xn>::type...> | |
279 | apply(Xn&& ...xn) { | |
280 | return basic_tuple<typename detail::decay<Xn>::type...>{ | |
281 | static_cast<Xn&&>(xn)... | |
282 | }; | |
283 | } | |
284 | }; | |
285 | ||
286 | #if 0 | |
287 | ////////////////////////////////////////////////////////////////////////// | |
288 | // length | |
289 | ////////////////////////////////////////////////////////////////////////// | |
290 | template <> | |
291 | struct length_impl<basic_tuple_tag> { | |
292 | template <typename ...Xn> | |
293 | static constexpr auto apply(basic_tuple<Xn...> const&) { | |
294 | return hana::size_c<sizeof...(Xn)>; | |
295 | } | |
296 | }; | |
297 | #endif | |
298 | BOOST_HANA_NAMESPACE_END | |
299 | ||
300 | #endif // !BOOST_HANA_BASIC_TUPLE_HPP |