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