Horizon
Loading...
Searching...
No Matches
common_tuple.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2013-present
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12//
13
14#ifndef RANGES_V3_UTILITY_COMMON_TUPLE_HPP
15#define RANGES_V3_UTILITY_COMMON_TUPLE_HPP
16
17#include <utility>
18
19#include <meta/meta.hpp>
20
21#include <concepts/concepts.hpp>
22
24
25#include <range/v3/detail/adl_get.hpp>
30
31#include <range/v3/detail/prologue.hpp>
32
33namespace ranges
34{
36 namespace detail
37 {
38 template<typename... Us, typename Tup, std::size_t... Is>
39 std::tuple<Us...> to_std_tuple(Tup && tup, meta::index_sequence<Is...>)
40 {
41 return std::tuple<Us...>{adl_get<Is>(static_cast<Tup &&>(tup))...};
42 }
43
44#ifdef RANGES_WORKAROUND_MSVC_786312
45 template<std::size_t, typename...>
46 struct args_;
47
48 template<typename, typename>
49 inline constexpr bool argstructible = false;
50 template<std::size_t N, typename... Ts, typename... Us>
51 inline constexpr bool argstructible<args_<N, Ts...>, args_<N, Us...>> =
52 (META_IS_CONSTRUCTIBLE(Ts, Us) && ...);
53
54 template<typename, typename>
55 inline constexpr bool argsignable = false;
56 template<std::size_t N, typename... Ts, typename... Us>
57 inline constexpr bool argsignable<args_<N, Ts...>, args_<N, Us...>> =
58 (std::is_assignable_v<Ts &, Us> && ...);
59#endif // RANGES_WORKAROUND_MSVC_786312
60
61 template<std::size_t N, typename... Ts>
62 struct args_
63 {
64 template<typename... Us>
65 args_(args_<N, Us...>, meta::if_c<
66#ifdef RANGES_WORKAROUND_MSVC_786312
67 argstructible<args_, args_<N, Us...>>
68#else // ^^^ workaround / no workaround vvv
69 meta::and_c<META_IS_CONSTRUCTIBLE(Ts,
70 Us)...>::value
71#endif // RANGES_WORKAROUND_MSVC_786312
72 > * = nullptr)
73 {}
74 template<typename... Us>
75 meta::if_c<
76#ifdef RANGES_WORKAROUND_MSVC_786312
77 argsignable<args_, args_<N, Us...>>,
78#else // ^^^ workaround / no workaround vvv
80#endif // RANGES_WORKAROUND_MSVC_786312
81 args_ &>
82 operator=(args_<N, Us...>)
83 {
84 return *this;
85 }
86 };
87 template<typename... Ts>
88 using args = args_<sizeof...(Ts), Ts...>;
89 template<typename... Ts>
90 using rargs = args_<sizeof...(Ts), Ts &...>;
91 } // namespace detail
93
94 template<typename... Ts>
95 struct common_tuple : _tuple_wrapper_::forward_tuple_interface<std::tuple<Ts...>>
96 {
97 private:
98 template<typename That, std::size_t... Is>
100 : common_tuple::forward_tuple_interface{
101 detail::adl_get<Is>(static_cast<That &&>(that))...}
102 {}
103 struct element_assign_
104 {
105 template<typename T, typename U>
106 int operator()(T & t, U && u) const
107 {
108 t = static_cast<U &&>(u);
109 return 0;
110 }
111 };
112
113 public:
114 // Construction
115 CPP_member
116 CPP_ctor(common_tuple)()( //
117 noexcept( //
118 meta::and_c<std::is_nothrow_default_constructible<Ts>::value...>::value)
119 requires default_constructible<std::tuple<Ts...>>)
120 : common_tuple::forward_tuple_interface{}
121 {}
122 template(typename... Us)(
123 requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
124 explicit common_tuple(Us &&... us) //
126 : common_tuple::forward_tuple_interface{static_cast<Us &&>(us)...}
127 {}
128 template(typename... Us)(
129 requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
130 common_tuple(std::tuple<Us...> & that) //
131 noexcept(
133 : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
134 {}
135 template(typename... Us)(
136 requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
137 common_tuple(std::tuple<Us...> const & that) //
138 noexcept(meta::and_c<
139 std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
140 : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
141 {}
142 template(typename... Us)(
143 requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
144 common_tuple(std::tuple<Us...> && that) //
145 noexcept(
147 : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
148 {}
149 template(typename... Us)(
150 requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
152 noexcept(
154 : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
155 {}
156 template(typename... Us)(
157 requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
158 common_tuple(common_tuple<Us...> const & that) //
159 noexcept(meta::and_c<
160 std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
161 : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
162 {}
163 template(typename... Us)(
164 requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
166 noexcept(
168 : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
169 {}
170
171 std::tuple<Ts...> & base() noexcept
172 {
173 return *this;
174 }
175 std::tuple<Ts...> const & base() const noexcept
176 {
177 return *this;
178 }
179
180 // Assignment
181 template(typename... Us)(
182 requires std::is_assignable<detail::args<Ts...> &,
183 detail::rargs<Us...>>::value) //
184 common_tuple & operator=(std::tuple<Us...> & that) noexcept(
186 {
187 (void)tuple_transform(base(), that, element_assign_{});
188 return *this;
189 }
190 template(typename... Us)(
191 requires std::is_assignable<detail::args<Ts...> &,
192 detail::rargs<Us const...>>::value) //
193 common_tuple & operator=(std::tuple<Us...> const & that) noexcept(
195 {
196 (void)tuple_transform(base(), that, element_assign_{});
197 return *this;
198 }
199 template(typename... Us)(
200 requires std::is_assignable<detail::args<Ts...> &,
201 detail::args<Us...>>::value) //
202 common_tuple & operator=(std::tuple<Us...> && that) noexcept(
204 {
205 (void)tuple_transform(base(), std::move(that), element_assign_{});
206 return *this;
207 }
208
209 template(typename... Us)(
210 requires std::is_assignable<detail::args<Ts const...> &,
211 detail::rargs<Us...>>::value)
212 common_tuple const & operator=(std::tuple<Us...> & that) const noexcept(
214 {
215 (void)tuple_transform(base(), that, element_assign_{});
216 return *this;
217 }
218 template(typename... Us)(
219 requires std::is_assignable<detail::args<Ts const...> &,
220 detail::rargs<Us const...>>::value)
221 common_tuple const & operator=(std::tuple<Us...> const & that) const
222 noexcept(meta::and_c<
223 std::is_nothrow_assignable<Ts const &, Us const &>::value...>::value)
224 {
225 (void)tuple_transform(base(), that, element_assign_{});
226 return *this;
227 }
228 template(typename... Us)(
229 requires std::is_assignable<detail::args<Ts const...> &,
230 detail::args<Us...>>::value)
231 common_tuple const & operator=(std::tuple<Us...> && that) const noexcept(
233 {
234 (void)tuple_transform(base(), std::move(that), element_assign_{});
235 return *this;
236 }
237
238 // Conversion
239 template(typename... Us)(
240 requires constructible_from<detail::args<Us...>, detail::rargs<Ts...>>)
241 operator std::tuple<Us...>() & noexcept(
242 meta::and_c<std::is_nothrow_constructible<Us, Ts &>::value...>::value)
243 {
244 return detail::to_std_tuple<Us...>(
245 *this, meta::make_index_sequence<sizeof...(Ts)>{});
246 }
247 template(typename... Us)(
248 requires constructible_from<detail::args<Us...>,
249 detail::rargs<Ts const...>>)
250 operator std::tuple<Us...>() const & noexcept(
251 meta::and_c<std::is_nothrow_constructible<Us, Ts const &>::value...>::value)
252 {
253 return detail::to_std_tuple<Us...>(
254 *this, meta::make_index_sequence<sizeof...(Ts)>{});
255 }
256 template(typename... Us)(
257 requires constructible_from<detail::args<Us...>, detail::args<Ts...>>)
258 operator std::tuple<Us...>() &&
259 noexcept(meta::and_c<std::is_nothrow_constructible<Us, Ts>::value...>::value)
260 {
261 return detail::to_std_tuple<Us...>(
262 std::move(*this), meta::make_index_sequence<sizeof...(Ts)>{});
263 }
264 };
265
266 // Logical operators
267#define LOGICAL_OP(OP, CONCEPT) \
268 template(typename... Ts, typename... Us)( \
269 requires and_v<CONCEPT<Ts, Us>...>) \
270 bool operator OP(common_tuple<Ts...> const & a, common_tuple<Us...> const & b) \
271 { \
272 return a.base() OP b.base(); \
273 } \
274 template(typename... Ts, typename... Us)( \
275 requires and_v<CONCEPT<Ts, Us>...>) \
276 bool operator OP(std::tuple<Ts...> const & a, common_tuple<Us...> const & b) \
277 { \
278 return a OP b.base(); \
279 } \
280 template(typename... Ts, typename... Us)( \
281 requires and_v<CONCEPT<Ts, Us>...>) \
282 bool operator OP(common_tuple<Ts...> const & a, std::tuple<Us...> const & b) \
283 { \
284 return a.base() OP b; \
285 } \
286
287 LOGICAL_OP(==, equality_comparable_with)
288 LOGICAL_OP(!=, equality_comparable_with)
289 LOGICAL_OP(<, totally_ordered_with)
290 LOGICAL_OP(<=, totally_ordered_with)
291 LOGICAL_OP(>, totally_ordered_with)
292 LOGICAL_OP(>=, totally_ordered_with)
293#undef LOGICAL_OP
294
296 {
297 template<typename... Args>
298 common_tuple<bind_element_t<Args>...> operator()(Args &&... args) const noexcept(
299 meta::and_c<std::is_nothrow_constructible<
300 bind_element_t<Args>, unwrap_reference_t<Args>>::value...>::value)
301 {
303 unwrap_reference(static_cast<Args &&>(args))...};
304 }
305 };
306
309 RANGES_INLINE_VARIABLE(make_common_tuple_fn, make_common_tuple)
310
311 template<typename F, typename S>
312 struct common_pair : std::pair<F, S>
313 {
314 private:
315 std::pair<F, S> const & base() const noexcept
316 {
317 return *this;
318 }
319
320 public:
321 // Construction
322 CPP_member
323 CPP_ctor(common_pair)()( //
324 noexcept(std::is_nothrow_default_constructible<F>::value && //
325 std::is_nothrow_default_constructible<S>::value) //
326 requires default_constructible<F> && default_constructible<S>)
327 : std::pair<F, S>{}
328 {}
329 template(typename F2, typename S2)(
330 requires constructible_from<F, F2> AND constructible_from<S, S2>)
331 common_pair(F2 && f2, S2 && s2) //
332 noexcept(std::is_nothrow_constructible<F, F2>::value &&
333 std::is_nothrow_constructible<S, S2>::value) //
334 : std::pair<F, S>{static_cast<F2 &&>(f2), static_cast<S2 &&>(s2)}
335 {}
336 template(typename F2, typename S2)(
337 requires constructible_from<F, F2 &> AND constructible_from<S, S2 &>)
338 common_pair(std::pair<F2, S2> & that) //
339 noexcept(std::is_nothrow_constructible<F, F2 &>::value &&
340 std::is_nothrow_constructible<S, S2 &>::value) //
341 : std::pair<F, S>{that.first, that.second}
342 {}
343 template(typename F2, typename S2)(
344 requires constructible_from<F, F2 const &> AND
345 constructible_from<S, S2 const &>)
346 common_pair(std::pair<F2, S2> const & that) //
347 noexcept(std::is_nothrow_constructible<F, F2 const &>::value &&
348 std::is_nothrow_constructible<S, S2 const &>::value) //
349 : std::pair<F, S>{that.first, that.second}
350 {}
351 template(typename F2, typename S2)(
352 requires constructible_from<F, F2> AND constructible_from<S, S2>)
353 common_pair(std::pair<F2, S2> && that) //
354 noexcept(std::is_nothrow_constructible<F, F2>::value &&
355 std::is_nothrow_constructible<S, S2>::value) //
356 : std::pair<F, S>{std::forward<F2>(that.first), std::forward<S2>(that.second)}
357 {}
358
359 // Conversion
360 template(typename F2, typename S2)(
361 requires constructible_from<F2, F &> AND constructible_from<S2, S &>)
362 operator std::pair<F2, S2>() & //
363 noexcept(std::is_nothrow_constructible<F2, F &>::value &&
364 std::is_nothrow_constructible<S2, S &>::value)
365 {
366 return {this->first, this->second};
367 }
368 template(typename F2, typename S2)(
369 requires constructible_from<F2, F const &> AND
370 constructible_from<S2, S const &>)
371 operator std::pair<F2, S2>() const & //
372 noexcept(std::is_nothrow_constructible<F2, F const &>::value &&
373 std::is_nothrow_constructible<S2, S const &>::value)
374 {
375 return {this->first, this->second};
376 }
377 template(typename F2, typename S2)(
378 requires constructible_from<F2, F> AND constructible_from<S2, S>)
379 operator std::pair<F2, S2>() &&
380 noexcept(std::is_nothrow_constructible<F2, F>::value &&
381 std::is_nothrow_constructible<S2, S>::value)
382 {
383 return {std::forward<F>(this->first), std::forward<S>(this->second)};
384 }
385
386 // Assignment
387 template(typename F2, typename S2)(
388 requires assignable_from<F &, F2 &> AND assignable_from<S &, S2 &>)
389 common_pair & operator=(std::pair<F2, S2> & that) //
390 noexcept(std::is_nothrow_assignable<F &, F2 &>::value &&
391 std::is_nothrow_assignable<S &, S2 &>::value)
392 {
393 this->first = that.first;
394 this->second = that.second;
395 return *this;
396 }
397 template(typename F2, typename S2)(
398 requires assignable_from<F &, F2 const &> AND
399 assignable_from<S &, S2 const &>)
400 common_pair & operator=(std::pair<F2, S2> const & that) //
401 noexcept(std::is_nothrow_assignable<F &, F2 const &>::value &&
402 std::is_nothrow_assignable<S &, S2 const &>::value)
403 {
404 this->first = that.first;
405 this->second = that.second;
406 return *this;
407 }
408 template(typename F2, typename S2)(
409 requires assignable_from<F &, F2> AND assignable_from<S &, S2>)
410 common_pair & operator=(std::pair<F2, S2> && that) //
411 noexcept(std::is_nothrow_assignable<F &, F2>::value &&
412 std::is_nothrow_assignable<S &, S2>::value)
413 {
414 this->first = static_cast<F2 &&>(that.first);
415 this->second = static_cast<S2 &&>(that.second);
416 return *this;
417 }
418
419 template(typename F2, typename S2)(
420 requires assignable_from<F const &, F2 &> AND
421 assignable_from<S const &, S2 &>)
422 common_pair const & operator=(std::pair<F2, S2> & that) const //
423 noexcept(std::is_nothrow_assignable<F const &, F2 &>::value &&
424 std::is_nothrow_assignable<S const &, S2 &>::value)
425 {
426 this->first = that.first;
427 this->second = that.second;
428 return *this;
429 }
430 template(typename F2, typename S2)(
431 requires assignable_from<F const &, F2 const &> AND
432 assignable_from<S const &, S2 const &>)
433 common_pair const & operator=(std::pair<F2, S2> const & that) const //
434 noexcept(std::is_nothrow_assignable<F const &, F2 const &>::value &&
435 std::is_nothrow_assignable<S const &, S2 const &>::value)
436 {
437 this->first = that.first;
438 this->second = that.second;
439 return *this;
440 }
441 template(typename F2, typename S2)(
442 requires assignable_from<F const &, F2> AND assignable_from<S const &, S2>)
443 common_pair const & operator=(std::pair<F2, S2> && that) const //
444 noexcept(std::is_nothrow_assignable<F const &, F2 &&>::value &&
445 std::is_nothrow_assignable<S const &, S2 &&>::value)
446 {
447 this->first = static_cast<F2 &&>(that.first);
448 this->second = static_cast<S2 &&>(that.second);
449 return *this;
450 }
451 };
452
453 // Logical operators
454 template(typename F1, typename S1, typename F2, typename S2)(
455 requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
456 bool operator==(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
457 {
458 return a.first == b.first && a.second == b.second;
459 }
460 template(typename F1, typename S1, typename F2, typename S2)(
461 requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
462 bool operator==(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
463 {
464 return a.first == b.first && a.second == b.second;
465 }
466 template(typename F1, typename S1, typename F2, typename S2)(
467 requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
468 bool operator==(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
469 {
470 return a.first == b.first && a.second == b.second;
471 }
472 template(typename F1, typename S1, typename F2, typename S2)(
473 requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
474 bool operator<(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
475 {
476 return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
477 }
478 template(typename F1, typename S1, typename F2, typename S2)(
479 requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
480 bool operator<(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
481 {
482 return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
483 }
484 template(typename F1, typename S1, typename F2, typename S2)(
485 requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
486 bool operator<(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
487 {
488 return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
489 }
490#define LOGICAL_OP(OP, CONCEPT, RET) \
491 template(typename F1, typename S1, typename F2, typename S2)( \
492 requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
493 bool operator OP(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
494 { \
495 return RET; \
496 } \
497 template(typename F1, typename S1, typename F2, typename S2)( \
498 requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
499 bool operator OP(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
500 { \
501 return RET; \
502 } \
503 template(typename F1, typename S1, typename F2, typename S2)( \
504 requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
505 bool operator OP(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b) \
506 { \
507 return RET; \
508 } \
509
510 LOGICAL_OP(!=, equality_comparable_with, !(a == b))
511 LOGICAL_OP(<=, totally_ordered_with, !(b < a))
512 LOGICAL_OP(>, totally_ordered_with, (b < a))
513 LOGICAL_OP(>=, totally_ordered_with, !(a < b))
514#undef LOGICAL_OP
515
517 {
518 template<typename First, typename Second, typename F = bind_element_t<First>,
519 typename S = bind_element_t<Second>>
520 common_pair<F, S> operator()(First && f, Second && s) const //
521 noexcept(std::is_nothrow_constructible<F, unwrap_reference_t<First>>::value &&
522 std::is_nothrow_constructible<F, unwrap_reference_t<Second>>::value)
523 {
524 return {unwrap_reference(static_cast<First &&>(f)),
525 unwrap_reference(static_cast<Second &&>(s))};
526 }
527 };
528
531 RANGES_INLINE_VARIABLE(make_common_pair_fn, make_common_pair)
532
533
534 namespace detail
535 {
536 template<typename, typename, typename, typename = void>
537 struct common_type_tuple_like
538 {};
539
540 template<template<typename...> class T0, typename... Ts,
541 template<typename...> class T1, typename... Us, typename TupleLike>
542 struct common_type_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
543 meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
545 meta::lazy::invoke<TupleLike, meta::lazy::_t<common_type<Ts, Us>>...>>
546 {};
547
548 template<typename, typename, typename, typename = void>
549 struct common_ref_tuple_like
550 {};
551
552 template<template<typename...> class T0, typename... Ts,
553 template<typename...> class T1, typename... Us, typename TupleLike>
554 struct common_ref_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
555 meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
556 : meta::lazy::let<meta::lazy::invoke<
557 TupleLike, meta::lazy::_t<common_reference<Ts, Us>>...>>
558 {};
559 } // namespace detail
561} // namespace ranges
562
564namespace concepts
565{
566 // common_type for pairs
567 template<typename F1, typename S1, typename F2, typename S2>
568 struct common_type<std::pair<F1, S1>, ranges::common_pair<F2, S2>>
569 : ranges::detail::common_type_tuple_like<
570 std::pair<F1, S1>, ranges::common_pair<F2, S2>,
571 meta::quote<ranges::common_pair>>
572 {};
573 template<typename F1, typename S1, typename F2, typename S2>
574 struct common_type<ranges::common_pair<F1, S1>, std::pair<F2, S2>>
575 : ranges::detail::common_type_tuple_like<
576 ranges::common_pair<F1, S1>, std::pair<F2, S2>,
577 meta::quote<ranges::common_pair>>
578 {};
579 template<typename F1, typename S1, typename F2, typename S2>
580 struct common_type<ranges::common_pair<F1, S1>, ranges::common_pair<F2, S2>>
581 : ranges::detail::common_type_tuple_like<ranges::common_pair<F1, S1>,
582 ranges::common_pair<F2, S2>,
583 meta::quote<ranges::common_pair>>
584 {};
585 // common_type for tuples
586 template<typename... Ts, typename... Us>
587 struct common_type<ranges::common_tuple<Ts...>, std::tuple<Us...>>
588 : ranges::detail::common_type_tuple_like<
589 ranges::common_tuple<Ts...>, std::tuple<Us...>,
590 meta::quote<ranges::common_tuple>>
591 {};
592 template<typename... Ts, typename... Us>
593 struct common_type<std::tuple<Ts...>, ranges::common_tuple<Us...>>
594 : ranges::detail::common_type_tuple_like<
595 std::tuple<Ts...>, ranges::common_tuple<Us...>,
596 meta::quote<ranges::common_tuple>>
597 {};
598 template<typename... Ts, typename... Us>
599 struct common_type<ranges::common_tuple<Ts...>, ranges::common_tuple<Us...>>
600 : ranges::detail::common_type_tuple_like<ranges::common_tuple<Ts...>,
601 ranges::common_tuple<Us...>,
602 meta::quote<ranges::common_tuple>>
603 {};
604
605 // common reference for pairs
606 template<typename F1, typename S1, typename F2, typename S2,
607 template<typename> class Qual1, template<typename> class Qual2>
608 struct basic_common_reference<ranges::common_pair<F1, S1>, std::pair<F2, S2>, Qual1,
609 Qual2>
610 : ranges::detail::common_ref_tuple_like<
611 ranges::common_pair<Qual1<F1>, Qual1<S1>>, std::pair<Qual2<F2>, Qual2<S2>>,
612 meta::quote<ranges::common_pair>>
613 {};
614 template<typename F1, typename S1, typename F2, typename S2,
615 template<typename> class Qual1, template<typename> class Qual2>
616 struct basic_common_reference<std::pair<F1, S1>, ranges::common_pair<F2, S2>, Qual1,
617 Qual2>
618 : ranges::detail::common_ref_tuple_like<
619 std::pair<Qual1<F1>, Qual1<S1>>, ranges::common_pair<Qual2<F2>, Qual2<S2>>,
620 meta::quote<ranges::common_pair>>
621 {};
622 template<typename F1, typename S1, typename F2, typename S2,
623 template<typename> class Qual1, template<typename> class Qual2>
624 struct basic_common_reference<ranges::common_pair<F1, S1>,
625 ranges::common_pair<F2, S2>, Qual1, Qual2>
626 : ranges::detail::common_ref_tuple_like<ranges::common_pair<Qual1<F1>, Qual1<S1>>,
627 ranges::common_pair<Qual2<F2>, Qual2<S2>>,
628 meta::quote<ranges::common_pair>>
629 {};
630 // common reference for tuples
631 template<typename... Ts, typename... Us, template<typename> class Qual1,
632 template<typename> class Qual2>
633 struct basic_common_reference<ranges::common_tuple<Ts...>, std::tuple<Us...>, Qual1,
634 Qual2>
635 : ranges::detail::common_ref_tuple_like<
636 ranges::common_tuple<Qual1<Ts>...>, std::tuple<Qual2<Us>...>,
637 meta::quote<ranges::common_tuple>>
638 {};
639 template<typename... Ts, typename... Us, template<typename> class Qual1,
640 template<typename> class Qual2>
641 struct basic_common_reference<std::tuple<Ts...>, ranges::common_tuple<Us...>, Qual1,
642 Qual2>
643 : ranges::detail::common_ref_tuple_like<
644 std::tuple<Qual1<Ts>...>, ranges::common_tuple<Qual2<Us>...>,
645 meta::quote<ranges::common_tuple>>
646 {};
647 template<typename... Ts, typename... Us, template<typename> class Qual1,
648 template<typename> class Qual2>
649 struct basic_common_reference<ranges::common_tuple<Ts...>,
650 ranges::common_tuple<Us...>, Qual1, Qual2>
651 : ranges::detail::common_ref_tuple_like<ranges::common_tuple<Qual1<Ts>...>,
652 ranges::common_tuple<Qual2<Us>...>,
653 meta::quote<ranges::common_tuple>>
654 {};
655} // namespace concepts
657
658RANGES_DIAGNOSTIC_PUSH
659RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
660RANGES_BEGIN_NAMESPACE_STD
661 template<typename First, typename Second>
662 struct tuple_size<::ranges::common_pair<First, Second>>
663 : std::integral_constant<size_t, 2>
664 {};
665
666 template<typename First, typename Second>
667 struct tuple_element<0, ::ranges::common_pair<First, Second>>
668 {
669 using type = First;
670 };
671
672 template<typename First, typename Second>
673 struct tuple_element<1, ::ranges::common_pair<First, Second>>
674 {
675 using type = Second;
676 };
677
678 template<typename... Ts>
679 struct tuple_size<::ranges::common_tuple<Ts...>>
680 : std::integral_constant<size_t, sizeof...(Ts)>
681 {};
682
683 template<size_t N, typename... Ts>
684 struct tuple_element<N, ::ranges::common_tuple<Ts...>>
685 : tuple_element<N, tuple<Ts...>>
686 {};
687
688#if RANGES_CXX_VER > RANGES_CXX_STD_17
689RANGES_BEGIN_NAMESPACE_VERSION
690 template<typename...>
691 struct common_type;
692
693 // common_type for pairs
694 template<typename F1, typename S1, typename F2, typename S2>
695 struct common_type<std::pair<F1, S1>, ::ranges::common_pair<F2, S2>>
696 : ::ranges::detail::common_type_tuple_like<
697 std::pair<F1, S1>, ::ranges::common_pair<F2, S2>,
699 {};
700 template<typename F1, typename S1, typename F2, typename S2>
701 struct common_type<::ranges::common_pair<F1, S1>, std::pair<F2, S2>>
702 : ::ranges::detail::common_type_tuple_like<
703 ::ranges::common_pair<F1, S1>, std::pair<F2, S2>,
704 ::meta::quote<::ranges::common_pair>>
705 {};
706 template<typename F1, typename S1, typename F2, typename S2>
707 struct common_type<::ranges::common_pair<F1, S1>, ::ranges::common_pair<F2, S2>>
708 : ::ranges::detail::common_type_tuple_like<::ranges::common_pair<F1, S1>,
709 ::ranges::common_pair<F2, S2>,
710 ::meta::quote<::ranges::common_pair>>
711 {};
712 // common_type for tuples
713 template<typename... Ts, typename... Us>
714 struct common_type<::ranges::common_tuple<Ts...>, std::tuple<Us...>>
715 : ::ranges::detail::common_type_tuple_like<
716 ::ranges::common_tuple<Ts...>, std::tuple<Us...>,
717 ::meta::quote<::ranges::common_tuple>>
718 {};
719 template<typename... Ts, typename... Us>
720 struct common_type<std::tuple<Ts...>, ::ranges::common_tuple<Us...>>
721 : ::ranges::detail::common_type_tuple_like<
722 std::tuple<Ts...>, ::ranges::common_tuple<Us...>,
723 ::meta::quote<::ranges::common_tuple>>
724 {};
725 template<typename... Ts, typename... Us>
726 struct common_type<::ranges::common_tuple<Ts...>, ::ranges::common_tuple<Us...>>
727 : ::ranges::detail::common_type_tuple_like<::ranges::common_tuple<Ts...>,
728 ::ranges::common_tuple<Us...>,
729 ::meta::quote<::ranges::common_tuple>>
730 {};
731
732 template<typename, typename, template<typename> class, template<typename> class>
733 struct basic_common_reference;
734
735 // common reference for pairs
736 template<typename F1, typename S1, typename F2, typename S2,
737 template<typename> class Qual1, template<typename> class Qual2>
738 struct basic_common_reference<::ranges::common_pair<F1, S1>, std::pair<F2, S2>, Qual1,
739 Qual2>
740 : ::ranges::detail::common_ref_tuple_like<
741 ::ranges::common_pair<Qual1<F1>, Qual1<S1>>, std::pair<Qual2<F2>, Qual2<S2>>,
742 ::meta::quote<::ranges::common_pair>>
743 {};
744 template<typename F1, typename S1, typename F2, typename S2,
745 template<typename> class Qual1, template<typename> class Qual2>
746 struct basic_common_reference<std::pair<F1, S1>, ::ranges::common_pair<F2, S2>, Qual1,
747 Qual2>
748 : ::ranges::detail::common_ref_tuple_like<
749 std::pair<Qual1<F1>, Qual1<S1>>, ::ranges::common_pair<Qual2<F2>, Qual2<S2>>,
750 ::meta::quote<::ranges::common_pair>>
751 {};
752 template<typename F1, typename S1, typename F2, typename S2,
753 template<typename> class Qual1, template<typename> class Qual2>
754 struct basic_common_reference<::ranges::common_pair<F1, S1>,
755 ::ranges::common_pair<F2, S2>, Qual1, Qual2>
756 : ::ranges::detail::common_ref_tuple_like<::ranges::common_pair<Qual1<F1>, Qual1<S1>>,
757 ::ranges::common_pair<Qual2<F2>, Qual2<S2>>,
758 ::meta::quote<::ranges::common_pair>>
759 {};
760 // common reference for tuples
761 template<typename... Ts, typename... Us, template<typename> class Qual1,
762 template<typename> class Qual2>
763 struct basic_common_reference<::ranges::common_tuple<Ts...>, std::tuple<Us...>, Qual1,
764 Qual2>
765 : ::ranges::detail::common_ref_tuple_like<
766 ::ranges::common_tuple<Qual1<Ts>...>, std::tuple<Qual2<Us>...>,
767 ::meta::quote<::ranges::common_tuple>>
768 {};
769 template<typename... Ts, typename... Us, template<typename> class Qual1,
770 template<typename> class Qual2>
771 struct basic_common_reference<std::tuple<Ts...>, ::ranges::common_tuple<Us...>, Qual1,
772 Qual2>
773 : ::ranges::detail::common_ref_tuple_like<
774 std::tuple<Qual1<Ts>...>, ::ranges::common_tuple<Qual2<Us>...>,
775 ::meta::quote<::ranges::common_tuple>>
776 {};
777 template<typename... Ts, typename... Us, template<typename> class Qual1,
778 template<typename> class Qual2>
779 struct basic_common_reference<::ranges::common_tuple<Ts...>,
780 ::ranges::common_tuple<Us...>, Qual1, Qual2>
781 : ::ranges::detail::common_ref_tuple_like<::ranges::common_tuple<Qual1<Ts>...>,
782 ::ranges::common_tuple<Qual2<Us>...>,
783 ::meta::quote<::ranges::common_tuple>>
784 {};
785RANGES_END_NAMESPACE_VERSION
786#endif // RANGES_CXX_VER > RANGES_CXX_STD_17
787RANGES_END_NAMESPACE_STD
788RANGES_DIAGNOSTIC_POP
789
790#include <range/v3/detail/epilogue.hpp>
791
792#endif
decltype(unwrap_reference(std::declval< T >())) unwrap_reference_t
Definition reference_wrapper.hpp:178
_t< detail::make_indices_< N, index_sequence< 0 >, detail::strategy_(1, N)> > make_index_sequence
Generate index_sequence containing integer constants [0,1,2,...,N-1].
Definition meta.hpp:473
list< F, S > pair
A list with exactly two elements.
Definition meta.hpp:2246
Tiny meta-programming library.
Tiny metaprogramming library.
Definition meta.hpp:116
Definition meta.hpp:1383
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition meta.hpp:787
A container for a sequence of compile-time integer constants.
Definition meta.hpp:434
Turn a template C into an invocable.
Definition meta.hpp:913
Definition common_tuple.hpp:313
Definition common_tuple.hpp:96
Definition common_tuple.hpp:517
Definition common_tuple.hpp:296