IDA C++ SDK 9.2
Loading...
Searching...
No Matches
qpair.hpp
Go to the documentation of this file.
1#pragma once
2#include <type_traits>
3#include <utility> // for std::swap (and optional interop)
4#include <cstddef>
5#include <tuple>
6
7template <class First, class Second>
8struct qpair
9{
10 using first_type = First;
11 using second_type = Second;
12
13 First first;
14 Second second;
15
16 // ctors
17 constexpr qpair() = default;
18 constexpr qpair(First const &a, Second const &b) : first(a), second(b) {}
19 constexpr qpair(First const &a, Second &&b) : first(a), second(std::move(b)) {}
20 constexpr qpair(First &&a, Second const &b) : first(std::move(a)), second(b) {}
21 constexpr qpair(First &&a, Second &&b) : first(std::move(a)), second(std::move(b)) {}
22
23 // converting ctor
24 template <class F2, class S2,
25 class = std::enable_if_t<std::is_constructible<First, F2 &&>::value && std::is_constructible<Second, S2 &&>::value>>
26 constexpr qpair(F2 &&a, S2 &&b) : first(std::forward<F2>(a)), second(std::forward<S2>(b)) {}
27
28 // copy/move
29 qpair(qpair const &) = default;
30 qpair(qpair &&) = default;
31 qpair &operator=(qpair const &) = default;
32 qpair &operator=(qpair &&) = default;
33
34 // from std::pair (lvalue)
35 template<class F2, class S2,
36 class = std::enable_if_t<std::is_constructible<First, F2 const &>::value && std::is_constructible<Second, S2 const &>::value>>
37 constexpr qpair(std::pair<F2, S2> const &p)
38 : first(p.first), second(p.second)
39 {
40 }
41
42 // from std::pair (rvalue) - moves
43 template<class F2, class S2,
44 class = std::enable_if_t<std::is_constructible<First, F2 &&>::value && std::is_constructible<Second, S2 &&>::value>>
45 constexpr qpair(std::pair<F2, S2> &&p)
46 : first(std::move(p.first)), second(std::move(p.second))
47 {
48 }
49
50 // qpair <- qpair (lvalue): enabled only if the types differ
51 template<class F2, class S2, std::enable_if_t<std::is_constructible<First, F2 const &>::value && std::is_constructible<Second, S2 const &>::value && !(std::is_same<First, F2>::value && std::is_same<Second, S2>::value), int> = 0 >
52 constexpr qpair(qpair<F2, S2> const &p)
53 : first(p.first), second(p.second)
54 {
55 }
56
57 // qpair <- qpair (rvalue): enabled only if the types differ
58 template<class F2, class S2, std::enable_if_t<std::is_constructible<First, F2 &&>::value && std::is_constructible<Second, S2 &&>::value && !(std::is_same<First, F2>::value && std::is_same<Second, S2>::value), int> = 0 >
59 constexpr qpair(qpair<F2, S2> &&p)
60 : first(std::forward<F2>(p.first)), second(std::forward<S2>(p.second))
61 {
62 }
63
64 void swap(qpair &other) noexcept(noexcept(std::swap(first, other.first)) &&
65 noexcept(std::swap(second, other.second)))
66 {
67 using std::swap;
68 swap(first, other.first);
69 swap(second, other.second);
70 }
71
72 // Optional: ease interop without exposing std::pair in signatures
73 template<class F2 = First, class S2 = Second>
74 explicit operator std::pair<std::decay_t<F2>, std::decay_t<S2>>() const { return { first, second }; }
75};
76
77template<class F, class S>
78inline void swap(qpair<F, S> &a, qpair<F, S> &b) noexcept(noexcept(a.swap(b)))
79{
80 a.swap(b);
81}
82
83// Helper: like std::make_pair - decays T1/T2 (refs, arrays, functions)
84template<class T1, class T2>
85constexpr qpair<std::decay_t<T1>, std::decay_t<T2>>
86make_qpair(T1 &&a, T2 &&b)
87{
88 return qpair<std::decay_t<T1>, std::decay_t<T2>>(
89 std::forward<T1>(a), std::forward<T2>(b));
90}
91
92// C++17 CTAD guide so `qpair{a,b}` deduces to qpair<decay_t<T1>, decay_t<T2>>
93template<class T1, class T2>
94qpair(T1, T2)->qpair<std::decay_t<T1>, std::decay_t<T2>>;
95
96// relational (lexicographic) - needed for map/set value_compare edge-cases
97template<class F, class S>
98constexpr bool operator==(qpair<F, S> const &a, qpair<F, S> const &b)
99{
100 return a.first == b.first && a.second == b.second;
101}
102template<class F, class S>
103constexpr bool operator!=(qpair<F, S> const &a, qpair<F, S> const &b)
104{
105 return !(a == b);
106}
107template<class F, class S>
108constexpr bool operator<(qpair<F, S> const &a, qpair<F, S> const &b)
109{
110 return (a.first < b.first) || (!(b.first < a.first) && a.second < b.second);
111}
112template<class F, class S>
113constexpr bool operator>(qpair<F, S> const &a, qpair<F, S> const &b)
114{
115 return b < a;
116}
117template<class F, class S>
118constexpr bool operator<=(qpair<F, S> const &a, qpair<F, S> const &b)
119{
120 return !(b < a);
121}
122template<class F, class S>
123constexpr bool operator>=(qpair<F, S> const &a, qpair<F, S> const &b)
124{
125 return !(a < b);
126}
127
128template <class T, class U>
129int compare(const qpair<T, U> &a, const qpair<T, U> &b)
130{
131 int code = compare(a.first, b.first);
132 if ( code != 0 )
133 return code;
134 return compare(a.second, b.second);
135}
136
137// get<N> support for structured bindings
138template<std::size_t I, class F, class S> constexpr auto &get(qpair<F, S> &p) noexcept
139{
140 static_assert(I < 2, "");
141 if constexpr ( I == 0 )
142 return p.first;
143 else
144 return p.second;
145}
146template<std::size_t I, class F, class S> constexpr auto const &get(qpair<F, S> const &p) noexcept
147{
148 static_assert(I < 2, "");
149 if constexpr ( I == 0 )
150 return p.first;
151 else
152 return p.second;
153}
154template<std::size_t I, class F, class S> constexpr auto &&get(qpair<F, S> &&p) noexcept
155{
156 static_assert(I < 2, "");
157 if constexpr ( I == 0 )
158 return std::move(p.first);
159 else
160 return std::move(p.second);
161}
162
163// tuple protocol specializations (allowed for user types)
164namespace std
165{
166 template<class F, class S> struct tuple_size<qpair<F, S>> : std::integral_constant<std::size_t, 2> {};
167 template<class F, class S> struct tuple_element<0, qpair<F, S>> { using type = F; };
168 template<class F, class S> struct tuple_element<1, qpair<F, S>> { using type = S; };
169}
int code
Definition fpro.h:88
Definition pro.h:3781
constexpr bool operator<(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:108
constexpr auto & get(qpair< F, S > &p) noexcept
Definition qpair.hpp:138
qpair(T1, T2) -> qpair< std::decay_t< T1 >, std::decay_t< T2 > >
constexpr qpair< std::decay_t< T1 >, std::decay_t< T2 > > make_qpair(T1 &&a, T2 &&b)
Definition qpair.hpp:86
constexpr bool operator!=(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:103
void swap(qpair< F, S > &a, qpair< F, S > &b) noexcept(noexcept(a.swap(b)))
Definition qpair.hpp:78
constexpr bool operator==(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:98
constexpr bool operator<=(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:118
constexpr bool operator>=(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:123
constexpr bool operator>(qpair< F, S > const &a, qpair< F, S > const &b)
Definition qpair.hpp:113
int compare(const qpair< T, U > &a, const qpair< T, U > &b)
Definition qpair.hpp:129
Definition qpair.hpp:9
void swap(qpair &other) noexcept(noexcept(std::swap(first, other.first)) &&noexcept(std::swap(second, other.second)))
Definition qpair.hpp:64
qpair(qpair &&)=default
constexpr qpair()=default
qpair & operator=(qpair const &)=default
First first_type
Definition qpair.hpp:10
constexpr qpair(First const &a, Second const &b)
Definition qpair.hpp:18
T second
Definition qpair.hpp:14
constexpr qpair(qpair< F2, S2 > const &p)
Definition qpair.hpp:52
constexpr qpair(F2 &&a, S2 &&b)
Definition qpair.hpp:26
Second second_type
Definition qpair.hpp:11
constexpr qpair(std::pair< F2, S2 > const &p)
Definition qpair.hpp:37
constexpr qpair(First &&a, Second const &b)
Definition qpair.hpp:20
qpair(qpair const &)=default
constexpr qpair(First &&a, Second &&b)
Definition qpair.hpp:21
constexpr qpair(std::pair< F2, S2 > &&p)
Definition qpair.hpp:45
qpair & operator=(qpair &&)=default
const Key first
Definition qpair.hpp:13
constexpr qpair(First const &a, Second &&b)
Definition qpair.hpp:19
constexpr qpair(qpair< F2, S2 > &&p)
Definition qpair.hpp:59
F type
Definition qpair.hpp:167
S type
Definition qpair.hpp:168