Stroika Library 3.0d18
 
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 KEY_TYPE is TYPICALLY equals_comparable, but not required to be so we can use Mapping<...> etc with a type
32 * that is not equals_comparable, but with an explicitly given equals_compare function.
33 *
34 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
35 * o static_assert (totally_ordered<KEY_TYPE> and totally_ordered<VALUE_TYPE> IMPLIES totally_ordered<KeyValuePair<...>>)
36 */
37 template <typename KEY_TYPE, typename VALUE_TYPE>
38 struct KeyValuePair {
39 public:
40 using KeyType = KEY_TYPE;
41
42 public:
43 using ValueType = VALUE_TYPE;
44
45 public:
46 /**
47 * Similar logic for what overloads are available to pair<>, but here we also allow construction from a 'pair<>'.
48 *
49 * @todo cleanup - should be BOTH simpler, and handle a bunch of other cases. See if I can find a good example. pair<> code
50 * from visual studio uses a bunch of requires and is even more complex.
51 */
52 constexpr KeyValuePair ()
53 requires (constructible_from<KEY_TYPE> and constructible_from<VALUE_TYPE>)
54 = default;
55 KeyValuePair (const KeyValuePair& src)
56 requires (copy_constructible<KEY_TYPE> and copy_constructible<VALUE_TYPE>)
57 = default;
59 requires (is_move_constructible_v<KEY_TYPE> and is_move_constructible_v<VALUE_TYPE>)
60 = default;
61 constexpr KeyValuePair (const KeyType& key, const ValueType& value)
62 requires (copy_constructible<KEY_TYPE> and copy_constructible<VALUE_TYPE>);
63 template <typename KEY_TYPE2, typename VALUE_TYPE2>
64 constexpr KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
65 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&> and constructible_from<VALUE_TYPE, const VALUE_TYPE2&>);
66 template <typename KEY_TYPE2, typename VALUE_TYPE2>
68 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&> and constructible_from<VALUE_TYPE, const VALUE_TYPE2&>);
69
70 public:
71 /**
72 */
73 nonvirtual KeyValuePair& operator= (const KeyValuePair& rhs) = default;
74 nonvirtual KeyValuePair& operator= (KeyValuePair&& rhs) = default;
75 template <typename KEY_TYPE2, typename VALUE_TYPE2>
76 nonvirtual KeyValuePair& operator= (const pair<KEY_TYPE2, VALUE_TYPE2>& rhs);
77 template <typename KEY_TYPE2, typename VALUE_TYPE2>
78 nonvirtual KeyValuePair& operator= (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& rhs);
79 template <typename KEY_TYPE2, typename VALUE_TYPE2>
80 nonvirtual KeyValuePair& operator= (pair<KEY_TYPE2, VALUE_TYPE2>&& rhs);
81 template <typename KEY_TYPE2, typename VALUE_TYPE2>
82 nonvirtual KeyValuePair& operator= (KeyValuePair<KEY_TYPE2, VALUE_TYPE2>&& rhs);
83
84 public:
85 KeyType fKey{};
86 ValueType fValue{};
87
88 public:
89 /**
90 * Define operator== in the obvious way key == key and value == value.
91 * This method is only defined if BOTH the key and value have a defined operator==
92 */
93 constexpr bool operator== (const KeyValuePair&) const
94 requires (equality_comparable<KEY_TYPE> and equality_comparable<VALUE_TYPE>);
95
96 public:
97 /**
98 * Define operator<=> in the obvious way key <=> key first, and then if equal, compare values.
99 * This method is only defined if BOTH the key and value have a defined spaceship operator
100 */
101 constexpr auto operator<=> (const KeyValuePair&) const
102 requires (three_way_comparable<KEY_TYPE> and three_way_comparable<VALUE_TYPE>);
103 };
104
105 template <typename KEY_TYPE>
106 struct KeyValuePair<KEY_TYPE, void> {
107 public:
108 using KeyType = KEY_TYPE;
109
110 public:
111 using ValueType = void;
112
113 public:
114 /**
115 * Similar logic for what overloads are available to pair<>, but here we also allow construction from a 'pair<>'.
116 *
117 * @todo cleanup - should be BOTH simpler, and handle a bunch of other cases. See if I can find a good example. pair<> code
118 * from visual studio uses a bunch of requires and is even more complex.
119 */
120 constexpr KeyValuePair ()
121 requires (constructible_from<KEY_TYPE>)
122 = default;
123 KeyValuePair (const KeyValuePair& src)
124 requires (copy_constructible<KEY_TYPE>)
125 = default;
127 requires (is_move_constructible_v<KEY_TYPE>)
128 = default;
129 constexpr KeyValuePair (const KeyType& key)
130 requires (copy_constructible<KEY_TYPE>);
131 template <typename KEY_TYPE2>
132 constexpr KeyValuePair (const pair<KEY_TYPE2, void>& src)
133 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&>);
134 template <typename KEY_TYPE2>
135 constexpr KeyValuePair (const KeyValuePair<KEY_TYPE2, void>& src)
136 requires (constructible_from<KEY_TYPE, const KEY_TYPE2&>);
137
138 public:
139 /**
140 */
141 nonvirtual KeyValuePair& operator= (const KeyValuePair& rhs) = default;
142 nonvirtual KeyValuePair& operator= (KeyValuePair&& rhs) = default;
143 template <typename KEY_TYPE2>
144 nonvirtual KeyValuePair& operator= (const pair<KEY_TYPE2, void>& rhs);
145 template <typename KEY_TYPE2>
146 nonvirtual KeyValuePair& operator= (const KeyValuePair<KEY_TYPE2, void>& rhs);
147 template <typename KEY_TYPE2>
148 nonvirtual KeyValuePair& operator= (pair<KEY_TYPE2, void>&& rhs);
149 template <typename KEY_TYPE2>
150 nonvirtual KeyValuePair& operator= (KeyValuePair<KEY_TYPE2, void>&& rhs);
151
152 public:
153 KeyType fKey{};
154
155 public:
156 /**
157 * Define operator== in the obvious way key == key and value == value.
158 * This method is only defined if BOTH the key and value have a defined operator==
159 */
160 constexpr bool operator== (const KeyValuePair&) const
161 requires (equality_comparable<KEY_TYPE>);
162
163 public:
164 /**
165 * Define operator<=> in the obvious way key <=> key first, and then if equal, compare values.
166 * This method is only defined if BOTH the key and value have a defined spaceship operator
167 */
168 constexpr auto operator<=> (const KeyValuePair&) const
169 requires (three_way_comparable<KEY_TYPE>);
170 };
171
172 namespace Private_ {
173#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
174 template <typename T1, typename T2 = void>
175 struct is_KVP_ : std::false_type {};
176 template <typename T1, typename T2>
177 struct is_KVP_<KeyValuePair<T1, T2>> : std::true_type {};
178#endif
179 }
180
181 /**
182 */
183 template <typename T>
184 concept IKeyValuePair =
185#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
186 Private_::is_KVP_<T>::value
187#else
188 requires (T t) {
189 {
190 []<typename T1, typename T2> (KeyValuePair<T1, T2>) {}(t)
191 };
192 }
193#endif
194 ;
195 static_assert (not IKeyValuePair<optional<int>>);
196 static_assert (IKeyValuePair<KeyValuePair<int, int>>);
197 static_assert (IKeyValuePair<KeyValuePair<int, void>>);
198
199}
200
201/*
202 ********************************************************************************
203 ***************************** Implementation Details ***************************
204 ********************************************************************************
205 */
206#include "KeyValuePair.inl"
207
208#endif /*_Stroika_Foundation_Common_KeyValuePair_h_*/
constexpr auto operator<=>(const KeyValuePair &) const
constexpr bool operator==(const KeyValuePair &) const