SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
common_pair.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <utility>
16 
17 #include <seqan3/core/platform.hpp>
18 
19 namespace seqan3
20 {
21 
26 template <class T1, class T2>
27 struct common_pair : public std::pair<T1, T2>
28 {
29 private:
31  using base_t = std::pair<T1, T2>;
32 
33 public:
37  common_pair() = default;
38  common_pair(common_pair const &) = default;
39  common_pair & operator=(common_pair const &) = default;
40  ~common_pair() = default;
42 
43  using base_t::first;
44  using base_t::second;
45 
50  template <class U1, class U2>
51  requires (std::is_constructible_v<T1, U1 &> && std::is_constructible_v<T2, U2 &>)
52  constexpr common_pair(U1 & first, U2 & second) : base_t(first, second)
53  {}
54 
55  template <class U1, class U2>
56  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
57  constexpr common_pair(U1 const & first, U2 const & second) : base_t(first, second)
58  {}
59 
60  template <class U1, class U2>
61  requires (std::is_constructible_v<T1, U1> && std::is_constructible_v<T2, U2>)
62  constexpr common_pair(U1 && first, U2 && second) : base_t(std::forward<U1>(first), std::forward<U2>(second))
63  {}
64 
65  template <class U1, class U2>
66  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
67  constexpr common_pair(U1 const && first, U2 const && second) :
68  base_t(std::forward<U1 const>(first), std::forward<U2 const>(second))
69  {}
72 
77  template <class U1, class U2>
78  requires (std::is_constructible_v<T1, U1 &> && std::is_constructible_v<T2, U2 &>)
79  constexpr common_pair(common_pair<U1, U2> & other) : base_t(other.first, other.second)
80  {}
81 
82  template <class U1, class U2>
83  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
84  constexpr common_pair(common_pair<U1, U2> const & other) : base_t(other.first, other.second)
85  {}
86 
87  template <class U1, class U2>
88  requires (std::is_constructible_v<T1, U1> && std::is_constructible_v<T2, U2>)
89  constexpr common_pair(common_pair<U1, U2> && other) :
90  base_t(std::forward<U1>(other.first), std::forward<U2>(other.second))
91  {}
92 
93  template <class U1, class U2>
94  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
95  constexpr common_pair(common_pair<U1, U2> const && other) :
96  base_t(std::forward<U1 const>(other.first), std::forward<U2 const>(other.second))
97  {}
100 
105  template <class U1, class U2>
106  requires (std::is_constructible_v<T1, U1 &> && std::is_constructible_v<T2, U2 &>)
107  constexpr common_pair(std::pair<U1, U2> & other) : base_t(other.first, other.second)
108  {}
109 
110  template <class U1, class U2>
111  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
112  constexpr common_pair(std::pair<U1, U2> const & other) : base_t(other.first, other.second)
113  {}
114 
115  template <class U1, class U2>
116  requires (std::is_constructible_v<T1, U1> && std::is_constructible_v<T2, U2>)
117  constexpr common_pair(std::pair<U1, U2> && other) :
118  base_t(std::forward<U1>(other.first), std::forward<U2>(other.second))
119  {}
120 
121  template <class U1, class U2>
122  requires (std::is_constructible_v<T1, U1 const> && std::is_constructible_v<T2, U2 const>)
123  constexpr common_pair(std::pair<U1, U2> const && other) :
124  base_t(std::forward<U1 const>(other.first), std::forward<U2 const>(other.second))
125  {}
128 
133  template <class U1, class U2>
134  requires (std::is_assignable_v<T1, U1 &> && std::is_assignable_v<T2, U2 &>)
135  constexpr common_pair & operator=(common_pair<U1, U2> & other)
136  {
137  first = other.first;
138  second = other.second;
139  return *this;
140  }
141 
142  template <class U1, class U2>
143  requires (std::is_assignable_v<T1, U1 const> && std::is_assignable_v<T2, U2 const>)
144  constexpr common_pair & operator=(common_pair<U1, U2> const & other)
145  {
146  first = other.first;
147  second = other.second;
148  return *this;
149  }
150 
151  template <class U1, class U2>
152  requires (std::is_assignable_v<T1, U1> && std::is_assignable_v<T2, U2>)
153  constexpr common_pair & operator=(common_pair<U1, U2> && other)
154  {
155  first = std::move(other.first);
156  second = std::move(other.second);
157  return *this;
158  }
159 
160  template <class U1, class U2>
161  requires (std::is_assignable_v<T1, U1 const> && std::is_assignable_v<T2, U2 const>)
162  constexpr common_pair & operator=(common_pair<U1, U2> const && other)
163  {
164  first = std::move(other.first);
165  second = std::move(other.second);
166  return *this;
167  }
168 
169  template <class U1, class U2>
170  requires (std::is_assignable_v<T1 const, U1 &> && std::is_assignable_v<T2 const, U2 &>)
171  constexpr common_pair const & operator=(common_pair<U1, U2> & other) const
172  {
173  first = other.first;
174  second = other.second;
175  return *this;
176  }
177 
178  template <class U1, class U2>
179  requires (std::is_assignable_v<T1 const, U1 const> && std::is_assignable_v<T2 const, U2 const>)
180  constexpr common_pair const & operator=(common_pair<U1, U2> const & other) const
181  {
182  first = other.first;
183  second = other.second;
184  return *this;
185  }
186 
187  template <class U1, class U2>
188  requires (std::is_assignable_v<T1 const, U1> && std::is_assignable_v<T2 const, U2>)
189  constexpr common_pair const & operator=(common_pair<U1, U2> && other) const
190  {
191  first = std::move(other.first);
192  second = std::move(other.second);
193  return *this;
194  }
195 
196  template <class U1, class U2>
197  requires (std::is_assignable_v<T1 const, U1 const> && std::is_assignable_v<T2 const, U2 const>)
198  constexpr common_pair const & operator=(common_pair<U1, U2> const && other) const
199  {
200  first = std::move(other.first);
201  second = std::move(other.second);
202  return *this;
203  }
206 
211  template <class U1, class U2>
212  requires (std::is_assignable_v<T1, U1 &> && std::is_assignable_v<T2, U2 &>)
213  constexpr common_pair & operator=(std::pair<U1, U2> & other)
214  {
215  first = other.first;
216  second = other.second;
217  return *this;
218  }
219 
220  template <class U1, class U2>
221  requires (std::is_assignable_v<T1, U1 const> && std::is_assignable_v<T2, U2 const>)
222  constexpr common_pair & operator=(std::pair<U1, U2> const & other)
223  {
224  first = other.first;
225  second = other.second;
226  return *this;
227  }
228 
229  template <class U1, class U2>
230  requires (std::is_assignable_v<T1, U1> && std::is_assignable_v<T2, U2>)
231  constexpr common_pair & operator=(std::pair<U1, U2> && other)
232  {
233  first = std::move(other.first);
234  second = std::move(other.second);
235  return *this;
236  }
237 
238  template <class U1, class U2>
239  requires (std::is_assignable_v<T1, U1 const> && std::is_assignable_v<T2, U2 const>)
240  constexpr common_pair & operator=(std::pair<U1, U2> const && other)
241  {
242  first = std::move(other.first);
243  second = std::move(other.second);
244  return *this;
245  }
246 
247  template <class U1, class U2>
248  requires (std::is_assignable_v<T1 const, U1 &> && std::is_assignable_v<T2 const, U2 &>)
249  constexpr common_pair const & operator=(std::pair<U1, U2> & other) const
250  {
251  first = other.first;
252  second = other.second;
253  return *this;
254  }
255 
256  template <class U1, class U2>
257  requires (std::is_assignable_v<T1 const, U1 const> && std::is_assignable_v<T2 const, U2 const>)
258  constexpr common_pair const & operator=(std::pair<U1, U2> const & other) const
259  {
260  first = other.first;
261  second = other.second;
262  return *this;
263  }
264 
265  template <class U1, class U2>
266  requires (std::is_assignable_v<T1 const, U1> && std::is_assignable_v<T2 const, U2>)
267  constexpr common_pair const & operator=(std::pair<U1, U2> && other) const
268  {
269  first = std::move(other.first);
270  second = std::move(other.second);
271  return *this;
272  }
273 
274  template <class U1, class U2>
275  requires (std::is_assignable_v<T1 const, U1 const> && std::is_assignable_v<T2 const, U2 const>)
276  constexpr common_pair const & operator=(std::pair<U1, U2> const && other) const
277  {
278  first = std::move(other.first);
279  second = std::move(other.second);
280  return *this;
281  }
284 
289  template <class U1, class U2>
290  requires (std::is_constructible_v<U1, T1 &> && std::is_constructible_v<U2, T2 &>)
291  operator std::pair<U1, U2>() &
292  {
293  return {first, second};
294  }
295 
296  template <class U1, class U2>
297  requires (std::is_constructible_v<U1, T1 const> && std::is_constructible_v<U2, T2 const>)
298  operator std::pair<U1, U2>() const &
299  {
300  return {first, second};
301  }
302 
303  template <class U1, class U2>
304  requires (std::is_constructible_v<U1, T1> && std::is_constructible_v<U2, T2>)
305  operator std::pair<U1, U2>() &&
306  {
307  return {std::move(first), std::move(second)};
308  }
309 
310  template <class U1, class U2>
311  requires (std::is_constructible_v<U1, T1 const> && std::is_constructible_v<U2, T2 const>)
312  operator std::pair<U1, U2>() const &&
313  {
314  return {std::move(first), std::move(second)};
315  }
318 
329  template <class U1, class U2>
330  requires (std::equality_comparable_with<T1, U1> && std::equality_comparable_with<T2, U2>)
331  constexpr friend bool operator==(common_pair const & lhs, common_pair<U1, U2> const & rhs)
332  {
333  return lhs.first == rhs.first && lhs.second == rhs.second;
334  }
335 
343  template <class U1, class U2>
344  requires (std::equality_comparable_with<T1, U1> && std::equality_comparable_with<T2, U2>)
345  constexpr friend bool operator!=(common_pair const & lhs, common_pair<U1, U2> const & rhs)
346  {
347  return lhs.first != rhs.first && lhs.second != rhs.second;
348  }
349 
357  template <class U1, class U2>
358  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
359  constexpr friend bool operator<(common_pair const & lhs, common_pair<U1, U2> const & rhs)
360  {
361  return lhs.first < rhs.first && lhs.second < rhs.second;
362  }
363 
371  template <class U1, class U2>
372  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
373  constexpr friend bool operator<=(common_pair const & lhs, common_pair<U1, U2> const & rhs)
374  {
375  return lhs.first <= rhs.first && lhs.second <= rhs.second;
376  }
377 
385  template <class U1, class U2>
386  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
387  constexpr friend bool operator>(common_pair const & lhs, common_pair<U1, U2> const & rhs)
388  {
389  return lhs.first > rhs.first && lhs.second > rhs.second;
390  }
391 
399  template <class U1, class U2>
400  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
401  constexpr friend bool operator>=(common_pair const & lhs, common_pair<U1, U2> const & rhs)
402  {
403  return lhs.first >= rhs.first && lhs.second >= rhs.second;
404  }
405 
406 #ifdef __cpp_lib_three_way_comparison
415  template <class U1, class U2>
416  requires (std::three_way_comparable_with<T1, U1> && std::three_way_comparable_with<T2, U2>)
417  constexpr friend std::common_comparison_category_t<std::compare_three_way_result_t<U1, T1>,
418  std::compare_three_way_result_t<U2, T2>>
419  operator<=>(common_pair const & lhs, common_pair<U1, U2> const & rhs)
420  {
421  if (auto cmp = lhs.first <=> rhs.first; cmp != 0)
422  return cmp;
423  return lhs.second <=> rhs.second;
424  }
425 #endif // __cpp_lib_three_way_comparison
427 
438  template <class U1, class U2>
439  requires (std::equality_comparable_with<T1, U1> && std::equality_comparable_with<T2, U2>)
440  constexpr friend bool operator==(common_pair const & lhs, std::pair<U1, U2> const & rhs)
441  {
442  return lhs.first == rhs.first && lhs.second == rhs.second;
443  }
444 
452  template <class U1, class U2>
453  requires (std::equality_comparable_with<T1, U1> && std::equality_comparable_with<T2, U2>)
454  constexpr friend bool operator!=(common_pair const & lhs, std::pair<U1, U2> const & rhs)
455  {
456  return lhs.first != rhs.first && lhs.second != rhs.second;
457  }
458 
466  template <class U1, class U2>
467  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
468  constexpr friend bool operator<(common_pair const & lhs, std::pair<U1, U2> const & rhs)
469  {
470  return lhs.first < rhs.first && lhs.second < rhs.second;
471  }
472 
480  template <class U1, class U2>
481  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
482  constexpr friend bool operator<=(common_pair const & lhs, std::pair<U1, U2> const & rhs)
483  {
484  return lhs.first <= rhs.first && lhs.second <= rhs.second;
485  }
486 
494  template <class U1, class U2>
495  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
496  constexpr friend bool operator>(common_pair const & lhs, std::pair<U1, U2> const & rhs)
497  {
498  return lhs.first > rhs.first && lhs.second > rhs.second;
499  }
500 
508  template <class U1, class U2>
509  requires (std::totally_ordered_with<T1, U1> && std::totally_ordered_with<T2, U2>)
510  constexpr friend bool operator>=(common_pair const & lhs, std::pair<U1, U2> const & rhs)
511  {
512  return lhs.first >= rhs.first && lhs.second >= rhs.second;
513  }
514 
515 #ifdef __cpp_lib_three_way_comparison
524  template <class U1, class U2>
525  requires (std::three_way_comparable_with<T1, U1> && std::three_way_comparable_with<T2, U2>)
526  constexpr friend std::common_comparison_category_t<std::compare_three_way_result_t<U1, T1>,
527  std::compare_three_way_result_t<U2, T2>>
528  operator<=>(common_pair const & lhs, std::pair<U1, U2> const & rhs)
529  {
530  if (auto cmp = lhs.first <=> rhs.first; cmp != 0)
531  return cmp;
532  return lhs.second <=> rhs.second;
533  }
534 #endif // __cpp_lib_three_way_comparison
536 };
537 
539 template <class T1, class T2>
541 
542 } // namespace seqan3
543 
545 namespace std
546 {
547 
548 template <class T1, class T2>
549 struct tuple_size<seqan3::common_pair<T1, T2>> : public tuple_size<std::pair<T1, T2>>
550 {};
551 
552 template <size_t index, class T1, class T2>
553 struct tuple_element<index, seqan3::common_pair<T1, T2>> : public tuple_element<index, std::pair<T1, T2>>
554 {};
555 
556 template <class T1, class T2, class U1, class U2>
558 struct common_type<seqan3::common_pair<T1, T2>, seqan3::common_pair<U1, U2>>
559 {
561 };
562 
563 template <class T1, class T2, class U1, class U2>
565 struct common_type<std::pair<T1, T2>, seqan3::common_pair<U1, U2>>
566 {
568 };
569 
570 template <class T1, class T2, class U1, class U2>
572 struct common_type<seqan3::common_pair<T1, T2>, std::pair<U1, U2>>
573 {
575 };
576 
577 template <class T1, class T2, class U1, class U2, template <class> class TQual, template <class> class UQual>
580  std::common_reference_t<TQual<T2>, UQual<U2>>>;
581  }
582 struct basic_common_reference<seqan3::common_pair<T1, T2>, seqan3::common_pair<U1, U2>, TQual, UQual>
583 {
585  std::common_reference_t<TQual<T2>, UQual<U2>>>;
586 };
587 
588 template <class T1, class T2, class U1, class U2, template <class> class TQual, template <class> class UQual>
591  std::common_reference_t<TQual<T2>, UQual<U2>>>;
592  }
593 struct basic_common_reference<std::pair<T1, T2>, seqan3::common_pair<U1, U2>, TQual, UQual>
594 {
596  std::common_reference_t<TQual<T2>, UQual<U2>>>;
597 };
598 
599 template <class T1, class T2, class U1, class U2, template <class> class TQual, template <class> class UQual>
602  std::common_reference_t<TQual<T2>, UQual<U2>>>;
603  }
604 struct basic_common_reference<seqan3::common_pair<T1, T2>, std::pair<U1, U2>, TQual, UQual>
605 {
607  std::common_reference_t<TQual<T2>, UQual<U2>>>;
608 };
609 
610 template <std::size_t i, class T1, class T2>
611 constexpr std::tuple_element_t<i, seqan3::common_pair<T1, T2>> & get(seqan3::common_pair<T1, T2> & t) noexcept
612  requires (i < 2)
613 {
614  return std::get<i>(static_cast<std::pair<T1, T2> &>(t));
615 }
616 
617 template <std::size_t i, class T1, class T2>
618 constexpr std::tuple_element_t<i, seqan3::common_pair<T1, T2>> const &
619 get(seqan3::common_pair<T1, T2> const & t) noexcept
620  requires (i < 2)
621 {
622  return std::get<i>(static_cast<std::pair<T1, T2> const &>(t));
623 }
624 
625 template <std::size_t i, class T1, class T2>
626 constexpr std::tuple_element_t<i, seqan3::common_pair<T1, T2>> && get(seqan3::common_pair<T1, T2> && t) noexcept
627  requires (i < 2)
628 {
629  return std::get<i>(static_cast<std::pair<T1, T2> &&>(std::move(t)));
630 }
631 
632 template <std::size_t i, class T1, class T2>
633 constexpr std::tuple_element_t<i, seqan3::common_pair<T1, T2>> const &&
634 get(seqan3::common_pair<T1, T2> const && t) noexcept
635  requires (i < 2)
636 {
637  return std::get<i>(static_cast<std::pair<T1, T2> const &&>(std::move(t)));
638 }
639 
640 template <typename type, class T1, class T2>
641 constexpr type & get(seqan3::common_pair<T1, T2> & t) noexcept
642  requires (!std::same_as<T1, T2>)
643 {
644  return std::get<type>(static_cast<std::pair<T1, T2> &>(t));
645 }
646 
647 template <typename type, class T1, class T2>
648 constexpr type const & get(seqan3::common_pair<T1, T2> const & t) noexcept
649  requires (!std::same_as<T1, T2>)
650 {
651  return std::get<type>(static_cast<std::pair<T1, T2> const &>(t));
652 }
653 
654 template <typename type, class T1, class T2>
655 constexpr type && get(seqan3::common_pair<T1, T2> && t) noexcept
656  requires (!std::same_as<T1, T2>)
657 {
658  return std::get<type>(static_cast<std::pair<T1, T2> &&>(std::move(t)));
659 }
660 
661 template <typename type, class T1, class T2>
662 constexpr type const && get(seqan3::common_pair<T1, T2> const && t) noexcept
663  requires (!std::same_as<T1, T2>)
664 {
665  return std::get<type>(static_cast<std::pair<T1, T2> const &&>(std::move(t)));
666 }
667 
668 } // namespace std
T forward(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:415
common_pair(T1, T2) -> common_pair< T1, T2 >
Class template argument deduction guide.
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Provides platform and dependency checks.
A std::pair implementation that incorporates most changes from C++23's standard library.
Definition: common_pair.hpp:28
common_pair(common_pair const &)=default
Defaulted.
~common_pair()=default
common_pair & operator=(common_pair const &)=default
Defaulted.
common_pair()=default
Defaulted.
U2 & second
Constructs from arguments.
Definition: common_pair.hpp:52
requires(std::is_constructible_v< T1, U1 & > &&std::is_constructible_v< T2, U2 & >) const expr common_pair(U1 &first
Constructs from arguments.