Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
KeyValuePair.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Common_KeyValuePair_h_
5#define _Stroika_Foundation_Common_KeyValuePair_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <compare>
10#include <concepts>
11#include <type_traits>
12#include <utility>
13
14#include "Stroika/Foundation/Common/Common.h"
15
16/**
17 * TODO:
18 * @todo Consider having KeyValuePair have an operator explict pair<Key,Value>() converter.
19 */
20
22
23 /**
24 * Essentially the same as pair<KEY_TYPE,VALUE_TYPE> but with more clearly named data elements
25 * (when used for mappings, or other key/value pairs).
26 *
27 * \note moderately interoperable with pair<>
28 *
29 * \note Supports KeyValuePair<T,void> - so second type maybe void (sometimes useful as degenerate case - e.g. SkipList)
30 *
31 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
32 * o static_assert (totally_ordered<KEY_TYPE> and totally_ordered<VALUE_TYPE> IMPLIES totally_ordered<KeyValuePair<...>>)
33 */
34 template <typename KEY_TYPE, typename VALUE_TYPE>
35 struct KeyValuePair {
36 public:
37 using KeyType = KEY_TYPE;
38
39 public:
40 using ValueType = VALUE_TYPE;
41
42 public:
43 /**
44 * Similar logic for what overloads are available to pair<>, but here we also allow construction from a 'pair<>'.
45 *
46 * @todo cleanup - should be BOTH simpler, and handle a bunch of other cases. See if I can find a good example. pair<> code
47 * from visual studio uses a bunch of requires and is even more complex.
48 */
49 constexpr KeyValuePair ()
50 requires (constructible_from<KEY_TYPE> and constructible_from<VALUE_TYPE>)
51 = default;
52 KeyValuePair (const KeyValuePair& src)
53 requires (copy_constructible<KEY_TYPE> and copy_constructible<VALUE_TYPE>)
54 = default;
56 requires (is_move_constructible_v<KEY_TYPE> and is_move_constructible_v<VALUE_TYPE>)
57 = default;
58 constexpr KeyValuePair (const KeyType& key, const ValueType& value)
59 requires (copy_constructible<KEY_TYPE> and copy_constructible<VALUE_TYPE>);
60 template <typename KEY_TYPE2, typename VALUE_TYPE2>
61 constexpr KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
62 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&> and constructible_from<VALUE_TYPE, const VALUE_TYPE2&>);
63 template <typename KEY_TYPE2, typename VALUE_TYPE2>
65 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&> and constructible_from<VALUE_TYPE, const VALUE_TYPE2&>);
66
67 public:
68 /**
69 */
70 nonvirtual KeyValuePair& operator= (const KeyValuePair& rhs) = default;
71 nonvirtual KeyValuePair& operator= (KeyValuePair&& rhs) = default;
72 template <typename KEY_TYPE2, typename VALUE_TYPE2>
73 nonvirtual KeyValuePair& operator= (const pair<KEY_TYPE2, VALUE_TYPE2>& rhs);
74 template <typename KEY_TYPE2, typename VALUE_TYPE2>
75 nonvirtual KeyValuePair& operator= (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& rhs);
76 template <typename KEY_TYPE2, typename VALUE_TYPE2>
77 nonvirtual KeyValuePair& operator= (pair<KEY_TYPE2, VALUE_TYPE2>&& rhs);
78 template <typename KEY_TYPE2, typename VALUE_TYPE2>
79 nonvirtual KeyValuePair& operator= (KeyValuePair<KEY_TYPE2, VALUE_TYPE2>&& rhs);
80
81 public:
82 KeyType fKey{};
83 ValueType fValue{};
84
85 public:
86 /**
87 * Define operator== in the obvious way key == key and value == value.
88 * This method is only defined if BOTH the key and value have a defined operator==
89 */
90 constexpr bool operator== (const KeyValuePair&) const
91 requires (equality_comparable<KEY_TYPE> and equality_comparable<VALUE_TYPE>);
92
93 public:
94 /**
95 * Define operator<=> in the obvious way key <=> key first, and then if equal, compare values.
96 * This method is only defined if BOTH the key and value have a defined spaceship operator
97 */
98 constexpr auto operator<=> (const KeyValuePair&) const
99 requires (three_way_comparable<KEY_TYPE> and three_way_comparable<VALUE_TYPE>);
100 };
101
102 template <typename KEY_TYPE>
103 struct KeyValuePair<KEY_TYPE, void> {
104 public:
105 using KeyType = KEY_TYPE;
106
107 public:
108 using ValueType = void;
109
110 public:
111 /**
112 * Similar logic for what overloads are available to pair<>, but here we also allow construction from a 'pair<>'.
113 *
114 * @todo cleanup - should be BOTH simpler, and handle a bunch of other cases. See if I can find a good example. pair<> code
115 * from visual studio uses a bunch of requires and is even more complex.
116 */
117 constexpr KeyValuePair ()
118 requires (constructible_from<KEY_TYPE>)
119 = default;
120 KeyValuePair (const KeyValuePair& src)
121 requires (copy_constructible<KEY_TYPE>)
122 = default;
124 requires (is_move_constructible_v<KEY_TYPE>)
125 = default;
126 constexpr KeyValuePair (const KeyType& key)
127 requires (copy_constructible<KEY_TYPE>);
128 template <typename KEY_TYPE2>
129 constexpr KeyValuePair (const pair<KEY_TYPE2, void>& src)
130 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&>);
131 template <typename KEY_TYPE2>
132 constexpr KeyValuePair (const KeyValuePair<KEY_TYPE2, void>& src)
133 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&>);
134
135 public:
136 /**
137 */
138 nonvirtual KeyValuePair& operator= (const KeyValuePair& rhs) = default;
139 nonvirtual KeyValuePair& operator= (KeyValuePair&& rhs) = default;
140 template <typename KEY_TYPE2>
141 nonvirtual KeyValuePair& operator= (const pair<KEY_TYPE2, void>& rhs);
142 template <typename KEY_TYPE2>
143 nonvirtual KeyValuePair& operator= (const KeyValuePair<KEY_TYPE2, void>& rhs);
144 template <typename KEY_TYPE2>
145 nonvirtual KeyValuePair& operator= (pair<KEY_TYPE2, void>&& rhs);
146 template <typename KEY_TYPE2>
147 nonvirtual KeyValuePair& operator= (KeyValuePair<KEY_TYPE2, void>&& rhs);
148
149 public:
150 KeyType fKey{};
151
152 public:
153 /**
154 * Define operator== in the obvious way key == key and value == value.
155 * This method is only defined if BOTH the key and value have a defined operator==
156 */
157 constexpr bool operator== (const KeyValuePair&) const
158 requires (equality_comparable<KEY_TYPE>);
159
160 public:
161 /**
162 * Define operator<=> in the obvious way key <=> key first, and then if equal, compare values.
163 * This method is only defined if BOTH the key and value have a defined spaceship operator
164 */
165 constexpr auto operator<=> (const KeyValuePair&) const
166 requires (three_way_comparable<KEY_TYPE>);
167 };
168
169 namespace Private_ {
170#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
171 template <typename T1, typename T2 = void>
172 struct is_KVP_ : std::false_type {};
173 template <typename T1, typename T2>
174 struct is_KVP_<KeyValuePair<T1, T2>> : std::true_type {};
175#endif
176 }
177
178 /**
179 */
180 template <typename T>
181 concept IKeyValuePair =
182#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
183 Private_::is_KVP_<T>::value
184#else
185 requires (T t) {
186 {
187 []<typename T1, typename T2> (KeyValuePair<T1, T2>) {}(t)
188 };
189 }
190#endif
191 ;
192 static_assert (not IKeyValuePair<optional<int>>);
193 static_assert (IKeyValuePair<KeyValuePair<int, int>>);
194 static_assert (IKeyValuePair<KeyValuePair<int, void>>);
195
196}
197
198/*
199 ********************************************************************************
200 ***************************** Implementation Details ***************************
201 ********************************************************************************
202 */
203#include "KeyValuePair.inl"
204
205#endif /*_Stroika_Foundation_Common_KeyValuePair_h_*/
constexpr auto operator<=>(const KeyValuePair &) const
constexpr bool operator==(const KeyValuePair &) const