Horizon
common_tuple.hpp
Go to the documentation of this file.
1 // 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 
23 #include <range/v3/range_fwd.hpp>
24 
25 #include <range/v3/detail/adl_get.hpp>
30 
31 #include <range/v3/detail/prologue.hpp>
32 
33 namespace 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) //
125  noexcept(meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value)
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(
132  meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
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(
146  meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
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(
153  meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
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(
167  meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
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(
185  meta::and_c<std::is_nothrow_assignable<Ts &, Us &>::value...>::value)
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(
194  meta::and_c<std::is_nothrow_assignable<Ts &, Us const &>::value...>::value)
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(
203  meta::and_c<std::is_nothrow_assignable<Ts &, Us>::value...>::value)
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(
213  meta::and_c<std::is_nothrow_assignable<Ts const &, Us &>::value...>::value)
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(
232  meta::and_c<std::is_nothrow_assignable<Ts const &, Us &&>::value...>::value)
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 
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)>>
544  : meta::lazy::let<
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 
564 namespace 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 
658 RANGES_DIAGNOSTIC_PUSH
659 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
660 RANGES_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
689 RANGES_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  {};
785 RANGES_END_NAMESPACE_VERSION
786 #endif // RANGES_CXX_VER > RANGES_CXX_STD_17
787 RANGES_END_NAMESPACE_STD
788 RANGES_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
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
_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
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
front< pop_front< Pair > > second
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2256
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