]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hana/tuple.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / hana / tuple.hpp
1 /*!
2 @file
3 Defines `boost::hana::tuple`.
4
5 @copyright Louis Dionne 2013-2017
6 @copyright Jason Rice 2017
7 Distributed under the Boost Software License, Version 1.0.
8 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
9 */
10
11 #ifndef BOOST_HANA_TUPLE_HPP
12 #define BOOST_HANA_TUPLE_HPP
13
14 #include <boost/hana/fwd/tuple.hpp>
15
16 #include <boost/hana/basic_tuple.hpp>
17 #include <boost/hana/bool.hpp>
18 #include <boost/hana/config.hpp>
19 #include <boost/hana/detail/decay.hpp>
20 #include <boost/hana/detail/fast_and.hpp>
21 #include <boost/hana/detail/index_if.hpp>
22 #include <boost/hana/detail/intrinsics.hpp>
23 #include <boost/hana/detail/operators/adl.hpp>
24 #include <boost/hana/detail/operators/comparable.hpp>
25 #include <boost/hana/detail/operators/iterable.hpp>
26 #include <boost/hana/detail/operators/monad.hpp>
27 #include <boost/hana/detail/operators/orderable.hpp>
28 #include <boost/hana/fwd/at.hpp>
29 #include <boost/hana/fwd/core/make.hpp>
30 #include <boost/hana/fwd/drop_front.hpp>
31 #include <boost/hana/fwd/index_if.hpp>
32 #include <boost/hana/fwd/is_empty.hpp>
33 #include <boost/hana/fwd/length.hpp>
34 #include <boost/hana/fwd/optional.hpp>
35 #include <boost/hana/fwd/unpack.hpp>
36 #include <boost/hana/type.hpp> // required by fwd decl of tuple_t
37
38 #include <cstddef>
39 #include <type_traits>
40 #include <utility>
41
42
43 BOOST_HANA_NAMESPACE_BEGIN
44 namespace detail {
45 template <typename Xs, typename Ys, std::size_t ...n>
46 constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
47 int sequence[] = {int{}, ((void)(
48 hana::at_c<n>(xs) = hana::at_c<n>(static_cast<Ys&&>(ys))
49 ), int{})...};
50 (void)sequence;
51 }
52
53 struct from_index_sequence_t { };
54
55 template <typename Tuple, typename ...Yn>
56 struct is_same_tuple : std::false_type { };
57
58 template <typename Tuple>
59 struct is_same_tuple<typename detail::decay<Tuple>::type, Tuple>
60 : std::true_type
61 { };
62
63 template <bool SameTuple, bool SameNumberOfElements, typename Tuple, typename ...Yn>
64 struct enable_tuple_variadic_ctor;
65
66 template <typename ...Xn, typename ...Yn>
67 struct enable_tuple_variadic_ctor<false, true, hana::tuple<Xn...>, Yn...>
68 : std::enable_if<
69 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
70 >
71 { };
72 }
73
74 //////////////////////////////////////////////////////////////////////////
75 // tuple
76 //////////////////////////////////////////////////////////////////////////
77 template <>
78 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
79 struct __declspec(empty_bases) tuple<> final
80 #else
81 struct tuple<> final
82 #endif
83 : detail::operators::adl<tuple<>>
84 , detail::iterable_operators<tuple<>>
85 {
86 constexpr tuple() { }
87 using hana_tag = tuple_tag;
88 };
89
90 template <typename ...Xn>
91 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
92 struct __declspec(empty_bases) tuple final
93 #else
94 struct tuple final
95 #endif
96 : detail::operators::adl<tuple<Xn...>>
97 , detail::iterable_operators<tuple<Xn...>>
98 {
99 basic_tuple<Xn...> storage_;
100 using hana_tag = tuple_tag;
101
102 private:
103 template <typename Other, std::size_t ...n>
104 explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
105 : storage_(hana::at_c<n>(static_cast<Other&&>(other))...)
106 { }
107
108 public:
109 template <typename ...dummy, typename = typename std::enable_if<
110 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
111 >::type>
112 constexpr tuple()
113 : storage_()
114 { }
115
116 template <typename ...dummy, typename = typename std::enable_if<
117 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
118 >::type>
119 constexpr tuple(Xn const& ...xn)
120 : storage_(xn...)
121 { }
122
123 template <typename ...Yn, typename = typename detail::enable_tuple_variadic_ctor<
124 detail::is_same_tuple<tuple, Yn...>::value,
125 sizeof...(Xn) == sizeof...(Yn), tuple, Yn...
126 >::type>
127 constexpr tuple(Yn&& ...yn)
128 : storage_(static_cast<Yn&&>(yn)...)
129 { }
130
131 template <typename ...Yn, typename = typename std::enable_if<
132 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
133 >::type>
134 constexpr tuple(tuple<Yn...> const& other)
135 : tuple(detail::from_index_sequence_t{},
136 std::make_index_sequence<sizeof...(Xn)>{},
137 other.storage_)
138 { }
139
140 template <typename ...Yn, typename = typename std::enable_if<
141 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
142 >::type>
143 constexpr tuple(tuple<Yn...>&& other)
144 : tuple(detail::from_index_sequence_t{},
145 std::make_index_sequence<sizeof...(Xn)>{},
146 static_cast<tuple<Yn...>&&>(other).storage_)
147 { }
148
149 // The three following constructors are required to make sure that
150 // the tuple(Yn&&...) constructor is _not_ preferred over the copy
151 // constructor for unary tuples containing a type that is constructible
152 // from tuple<...>. See test/tuple/cnstr.trap.cpp
153 template <typename ...dummy, typename = typename std::enable_if<
154 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
155 >::type>
156 constexpr tuple(tuple const& other)
157 : tuple(detail::from_index_sequence_t{},
158 std::make_index_sequence<sizeof...(Xn)>{},
159 other.storage_)
160 { }
161
162 template <typename ...dummy, typename = typename std::enable_if<
163 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
164 >::type>
165 constexpr tuple(tuple& other)
166 : tuple(const_cast<tuple const&>(other))
167 { }
168
169 template <typename ...dummy, typename = typename std::enable_if<
170 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
171 >::type>
172 constexpr tuple(tuple&& other)
173 : tuple(detail::from_index_sequence_t{},
174 std::make_index_sequence<sizeof...(Xn)>{},
175 static_cast<tuple&&>(other).storage_)
176 { }
177
178
179 template <typename ...Yn, typename = typename std::enable_if<
180 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
181 >::type>
182 constexpr tuple& operator=(tuple<Yn...> const& other) {
183 detail::assign(this->storage_, other.storage_,
184 std::make_index_sequence<sizeof...(Xn)>{});
185 return *this;
186 }
187
188 template <typename ...Yn, typename = typename std::enable_if<
189 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
190 >::type>
191 constexpr tuple& operator=(tuple<Yn...>&& other) {
192 detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
193 std::make_index_sequence<sizeof...(Xn)>{});
194 return *this;
195 }
196 };
197
198 //////////////////////////////////////////////////////////////////////////
199 // Operators
200 //////////////////////////////////////////////////////////////////////////
201 namespace detail {
202 template <>
203 struct comparable_operators<tuple_tag> {
204 static constexpr bool value = true;
205 };
206 template <>
207 struct orderable_operators<tuple_tag> {
208 static constexpr bool value = true;
209 };
210 template <>
211 struct monad_operators<tuple_tag> {
212 static constexpr bool value = true;
213 };
214 }
215
216 //////////////////////////////////////////////////////////////////////////
217 // Foldable
218 //////////////////////////////////////////////////////////////////////////
219 template <>
220 struct unpack_impl<tuple_tag> {
221 template <typename F>
222 static constexpr decltype(auto) apply(tuple<>&&, F&& f)
223 { return static_cast<F&&>(f)(); }
224 template <typename F>
225 static constexpr decltype(auto) apply(tuple<>&, F&& f)
226 { return static_cast<F&&>(f)(); }
227 template <typename F>
228 static constexpr decltype(auto) apply(tuple<> const&, F&& f)
229 { return static_cast<F&&>(f)(); }
230
231 template <typename Xs, typename F>
232 static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
233 return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
234 }
235 };
236
237 template <>
238 struct length_impl<tuple_tag> {
239 template <typename ...Xs>
240 static constexpr auto apply(tuple<Xs...> const&)
241 { return hana::size_c<sizeof...(Xs)>; }
242 };
243
244 //////////////////////////////////////////////////////////////////////////
245 // Iterable
246 //////////////////////////////////////////////////////////////////////////
247 template <>
248 struct at_impl<tuple_tag> {
249 template <typename Xs, typename N>
250 static constexpr decltype(auto) apply(Xs&& xs, N const&) {
251 constexpr std::size_t index = N::value;
252 return hana::at_c<index>(static_cast<Xs&&>(xs).storage_);
253 }
254 };
255
256 template <>
257 struct drop_front_impl<tuple_tag> {
258 template <std::size_t N, typename Xs, std::size_t ...i>
259 static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
260 return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
261 }
262
263 template <typename Xs, typename N>
264 static constexpr auto apply(Xs&& xs, N const&) {
265 constexpr std::size_t len = decltype(hana::length(xs))::value;
266 return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
267 (N::value < len) ? len - N::value : 0
268 >{});
269 }
270 };
271
272 template <>
273 struct is_empty_impl<tuple_tag> {
274 template <typename ...Xs>
275 static constexpr auto apply(tuple<Xs...> const&)
276 { return hana::bool_c<sizeof...(Xs) == 0>; }
277 };
278
279 // compile-time optimizations (to reduce the # of function instantiations)
280 template <std::size_t n, typename ...Xs>
281 constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
282 return hana::at_c<n>(xs.storage_);
283 }
284
285 template <std::size_t n, typename ...Xs>
286 constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
287 return hana::at_c<n>(xs.storage_);
288 }
289
290 template <std::size_t n, typename ...Xs>
291 constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
292 return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
293 }
294
295 template <>
296 struct index_if_impl<tuple_tag> {
297 template <typename ...Xs, typename Pred>
298 static constexpr auto apply(tuple<Xs...> const&, Pred const&)
299 -> typename detail::index_if<Pred, Xs...>::type
300 { return {}; }
301 };
302
303 //////////////////////////////////////////////////////////////////////////
304 // Sequence
305 //////////////////////////////////////////////////////////////////////////
306 template <>
307 struct Sequence<tuple_tag> {
308 static constexpr bool value = true;
309 };
310
311 template <>
312 struct make_impl<tuple_tag> {
313 template <typename ...Xs>
314 static constexpr
315 tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
316 { return {static_cast<Xs&&>(xs)...}; }
317 };
318 BOOST_HANA_NAMESPACE_END
319
320 #endif // !BOOST_HANA_TUPLE_HPP