11#include < beman/inplace_vector/inplace_vector.hpp>
22#include < gtest/gtest.h>
33
4+ #include < cmath>
45#include < compare>
56
67using namespace beman ;
@@ -10,57 +11,96 @@ concept has_threeway = requires(const T &t) {
1011 { t <=> t };
1112};
1213
13- TEST (Compare, threeway_int) {
14- using T = inplace_vector<int , 4 >;
15- T empty{};
16- T base{1 , 2 , 3 };
17- T copy = base;
14+ template <typename T> struct vec_list {
15+ T empty;
16+ T base; // base
17+ T copy; // identical to base
18+ T greater; // greater number of elements
19+ T lesser; // lesser number of elements
20+ T bigger; // bigger value of the elements
21+ T smaller; // smaller value of the elements
22+ T greater_smaller; // greater number of elements but smaller values
23+ T lesser_bigger; // lesser number of elements but bigger values
24+ };
1825
19- T greater{4 , 5 , 6 };
20- T lesser{0 , 0 , 0 };
26+ template <typename T> static void runtests (vec_list<T> &list) {
2127
22- T bigger{1 , 2 , 3 , 0 };
23- T smaller{1 , 2 };
28+ static_assert (std::three_way_comparable<T>);
2429
25- T greater_smaller{ 2 , 2 };
26- T lesser_bigger{ 0 , 2 , 3 , 0 };
30+ // if T::value_type is threewaycomparable with ordering X then T must also
31+ // be comparable with ordering X
2732
28- EXPECT_TRUE ((base <=> copy) == 0 );
29- EXPECT_TRUE ((base <=> greater) < 0 );
30- EXPECT_TRUE ((base <=> lesser) > 0 );
33+ using VT = typename T::value_type;
3134
32- EXPECT_TRUE ((base <=> bigger) < 0 );
33- EXPECT_TRUE ((base <=> smaller) > 0 );
35+ if constexpr (std::three_way_comparable<VT, std::strong_ordering>)
36+ static_assert (std::three_way_comparable<T, std::strong_ordering> );
3437
35- EXPECT_TRUE ((base <=> greater_smaller) < 0 );
36- EXPECT_TRUE ((base <=> lesser_bigger) > 0 );
37- }
38+ if constexpr (std::three_way_comparable<VT, std::weak_ordering>)
39+ static_assert (std::three_way_comparable<T, std::weak_ordering>);
40+
41+ if constexpr (std::three_way_comparable<VT, std::partial_ordering>)
42+ static_assert (std::three_way_comparable<T, std::partial_ordering>);
43+
44+ EXPECT_TRUE (list.empty == list.empty );
45+ EXPECT_TRUE (list.empty != list.base );
46+
47+ EXPECT_TRUE ((list.base <=> list.copy ) == 0 );
48+ EXPECT_TRUE ((list.base <=> list.greater ) < 0 );
49+ EXPECT_TRUE ((list.base <=> list.lesser ) > 0 );
3850
39- TEST (COmpare, threeway_float) {
40- using T = inplace_vector<float , 4 >;
41- T empty{};
42- T base{1 .0f , 2 .0f , 3 .0f };
43- T copy = base;
51+ EXPECT_TRUE ((list.base <=> list.bigger ) < 0 );
52+ EXPECT_TRUE ((list.base <=> list.smaller ) > 0 );
4453
45- T greater{ 4 . 0f , 5 . 0f , 6 . 0f } ;
46- T lesser{ 0 . 0f , 0 . 0f , 0 . 0f } ;
54+ EXPECT_TRUE ((list. base <=> list. greater_smaller ) < 0 ) ;
55+ EXPECT_TRUE ((list. base <=> list. lesser_bigger ) > 0 ) ;
4756
48- T bigger{1 .0f , 2 .0f , 3 .0f , 0 .0f };
49- T smaller{1 .0f , 2 .0f };
57+ EXPECT_TRUE (list.base == list.copy );
58+ EXPECT_TRUE (list.base <= list.copy );
59+ EXPECT_TRUE (list.base >= list.copy );
60+ EXPECT_TRUE (list.base < list.greater );
61+ EXPECT_TRUE (list.base <= list.greater );
62+ EXPECT_TRUE (list.base > list.lesser );
63+ EXPECT_TRUE (list.base >= list.lesser );
5064
51- T greater_smaller{2 .0f , 2 .0f };
52- T lesser_bigger{0 .0f , 2 .0f , 3 .0f , 0 .0f };
65+ EXPECT_TRUE (list.copy == list.base );
66+ EXPECT_TRUE (list.copy <= list.base );
67+ EXPECT_TRUE (list.copy >= list.base );
68+ EXPECT_TRUE (list.greater > list.base );
69+ EXPECT_TRUE (list.greater >= list.base );
70+ EXPECT_TRUE (list.lesser < list.base );
71+ EXPECT_TRUE (list.lesser <= list.base );
72+ };
5373
54- EXPECT_TRUE ((base <=> copy) == 0 );
74+ TEST (Compare, threeway_int) {
75+ vec_list<inplace_vector<int , 4 >> list{
76+ .empty {},
77+ .base {1 , 2 , 3 },
78+ .copy {1 , 2 , 3 },
79+ .greater {4 , 5 , 6 },
80+ .lesser {0 , 0 , 0 },
81+ .bigger {1 , 2 , 3 , 0 },
82+ .smaller {1 , 2 },
83+ .greater_smaller {2 , 2 },
84+ .lesser_bigger {0 , 2 , 3 , 4 },
85+ };
5586
56- EXPECT_TRUE ((base <=> greater) < 0 );
57- EXPECT_TRUE ((base <=> lesser) > 0 );
87+ runtests (list );
88+ }
5889
59- EXPECT_TRUE ((base <=> bigger) < 0 );
60- EXPECT_TRUE ((base <=> smaller) > 0 );
90+ TEST (Compare, threeway_float) {
91+ vec_list<inplace_vector<float , 4 >> list{
92+ .empty {},
93+ .base {1 .0f , 2 .0f , 3 .0f },
94+ .copy {1 .0f , 2 .0f , 3 .0f },
95+ .greater {4 .0f , 5 .0f , 6 .0f },
96+ .lesser {0 .0f , 0 .0f , 0 .0f },
97+ .bigger {1 .0f , 2 .0f , 3 .0f , 0 .0f },
98+ .smaller {1 .0f , 2 .0f },
99+ .greater_smaller {2 .0f , 2 .0f },
100+ .lesser_bigger {0 .0f , 2 .0f , 3 .0f , 4 .0f },
101+ };
61102
62- EXPECT_TRUE ((base <=> greater_smaller) < 0 );
63- EXPECT_TRUE ((base <=> lesser_bigger) > 0 );
103+ runtests (list);
64104}
65105
66106TEST (Compare, threeway_comparable1) {
@@ -75,32 +115,19 @@ TEST(Compare, threeway_comparable1) {
75115 static_assert (std::three_way_comparable<inplace_vector<comparable1, 4 >>);
76116 static_assert (has_threeway<inplace_vector<comparable1, 4 >>);
77117
78- using T = inplace_vector<comparable1, 4 >;
79-
80- T empty{};
81-
82- T base{{1 , 2 }, {3 , 4 }};
83- T copy = base;
84- T greater{{5 , 6 }, {7 , 8 }};
85- T lesser{{0 , 0 }, {0 , 0 }};
86-
87- T bigger{{1 , 2 }, {3 , 4 }, {5 , 6 }};
88- T smaller{{1 , 2 }};
89-
90- T greater_smaller{{2 , 2 }, {3 , 3 }};
91- T lesser_bigger{{0 , 2 }, {3 , 3 }, {0 , 0 }};
92-
93- EXPECT_TRUE ((empty <=> empty) == 0 );
94- EXPECT_TRUE ((base <=> copy) == 0 );
95-
96- EXPECT_TRUE ((base <=> greater) < 0 );
97- EXPECT_TRUE ((base <=> lesser) > 0 );
98-
99- EXPECT_TRUE ((base <=> bigger) < 0 );
100- EXPECT_TRUE ((base <=> smaller) > 0 );
118+ vec_list<inplace_vector<comparable1, 4 >> list{
119+ .empty {},
120+ .base {{1 , 2 }, {3 , 4 }},
121+ .copy {{1 , 2 }, {3 , 4 }},
122+ .greater {{5 , 6 }, {7 , 8 }},
123+ .lesser {{0 , 0 }, {0 , 0 }},
124+ .bigger {{1 , 2 }, {3 , 4 }, {5 , 6 }},
125+ .smaller {{1 , 2 }},
126+ .greater_smaller {{2 , 2 }, {3 , 3 }},
127+ .lesser_bigger {{0 , 2 }, {3 , 3 }, {4 , 4 }},
128+ };
101129
102- EXPECT_TRUE ((base <=> greater_smaller) < 0 );
103- EXPECT_TRUE ((base <=> lesser_bigger) > 0 );
130+ runtests (list);
104131}
105132
106133TEST (Compare, threeway_comparable2) {
@@ -119,31 +146,136 @@ TEST(Compare, threeway_comparable2) {
119146 static_assert (std::three_way_comparable<inplace_vector<comparable2, 4 >>);
120147 static_assert (has_threeway<inplace_vector<comparable2, 4 >>);
121148
122- using T = inplace_vector<comparable2, 4 >;
149+ vec_list<inplace_vector<comparable2, 4 >> list{
150+ .empty {},
151+ .base {{1 , 2 }, {3 , 4 }},
152+ .copy {{1 , 2 }, {3 , 4 }},
153+ .greater {{5 , 6 }, {7 , 8 }},
154+ .lesser {{0 , 0 }, {0 , 0 }},
155+ .bigger {{1 , 2 }, {3 , 4 }, {5 , 6 }},
156+ .smaller {{1 , 2 }},
157+ .greater_smaller {{2 , 2 }, {3 , 3 }},
158+ .lesser_bigger {{0 , 2 }, {3 , 3 }, {4 , 4 }},
159+ };
160+
161+ runtests (list);
162+
163+ // compare unorderable values
164+
165+ EXPECT_EQ (std::nanf (" " ) <=> std::nanf (" " ), std::partial_ordering::unordered);
166+ EXPECT_FALSE (std::nanf (" " ) == std::nanf (" " ));
167+ EXPECT_FALSE (std::nanf (" " ) < std::nanf (" " ));
168+ EXPECT_FALSE (std::nanf (" " ) > std::nanf (" " ));
169+ EXPECT_FALSE (std::nanf (" " ) >= std::nanf (" " ));
170+ EXPECT_FALSE (std::nanf (" " ) <= std::nanf (" " ));
171+
172+ inplace_vector<float , 4 > vnan{std::nanf (" " )};
173+ inplace_vector<float , 4 > vnan2{std::nanf (" " )};
123174
124- T empty{};
125- T base{{1 , 2 }, {3 , 4 }};
126- T copy = base;
127- T greater{{5 , 6 }, {7 , 8 }};
128- T lesser{{0 , 0 }, {0 , 0 }};
175+ EXPECT_EQ (vnan <=> vnan2, std::partial_ordering::unordered);
176+ EXPECT_FALSE (vnan == vnan2);
177+ EXPECT_FALSE (vnan < vnan2);
178+ EXPECT_FALSE (vnan > vnan2);
179+ EXPECT_FALSE (vnan >= vnan2);
180+ EXPECT_FALSE (vnan <= vnan2);
181+ }
182+
183+ TEST (Compare, threeway_strong_ordering) {
184+
185+ struct weaktype {
186+ int a;
187+ constexpr std::strong_ordering
188+ operator <=>(const weaktype &other) const = default ;
189+ };
190+
191+ using T = weaktype;
192+
193+ vec_list<inplace_vector<weaktype, 4 >> list{
194+ .empty {},
195+ .base {T{1 }, T{2 }, T{3 }},
196+ .copy {T{1 }, T{2 }, T{3 }},
197+ .greater {T{4 }, T{5 }, T{6 }},
198+ .lesser {T{0 }, T{0 }, T{0 }},
199+ .bigger {T{1 }, T{2 }, T{3 }, T{0 }},
200+ .smaller {T{1 }, T{2 }},
201+ .greater_smaller {T{2 }, T{2 }},
202+ .lesser_bigger {T{0 }, T{2 }, T{3 }, T{4 }},
203+ };
204+
205+ runtests (list);
206+ }
207+
208+ TEST (Compare, threeway_weak_ordering) {
209+
210+ struct weaktype {
211+ int a;
212+ constexpr std::weak_ordering
213+ operator <=>(const weaktype &other) const = default ;
214+ };
215+
216+ using T = weaktype;
217+
218+ vec_list<inplace_vector<weaktype, 4 >> list{
219+ .empty {},
220+ .base {T{1 }, T{2 }, T{3 }},
221+ .copy {T{1 }, T{2 }, T{3 }},
222+ .greater {T{4 }, T{5 }, T{6 }},
223+ .lesser {T{0 }, T{0 }, T{0 }},
224+ .bigger {T{1 }, T{2 }, T{3 }, T{0 }},
225+ .smaller {T{1 }, T{2 }},
226+ .greater_smaller {T{2 }, T{2 }},
227+ .lesser_bigger {T{0 }, T{2 }, T{3 }, T{4 }},
228+ };
229+
230+ runtests (list);
231+ }
232+
233+ TEST (Compare, threeway_partial_ordering) {
129234
130- T bigger{{1 , 2 }, {3 , 4 }, {5 , 6 }};
131- T smaller{{1 , 2 }};
235+ struct custom {
236+ int a;
237+ constexpr auto operator <=>(const custom &other) const {
238+ if (a == -1 && other.a == -1 )
239+ return std::partial_ordering::unordered;
240+ return std::partial_ordering (a <=> other.a );
241+ }
242+
243+ constexpr bool operator ==(const custom &other) const {
244+ if (a == -1 && other.a == -1 )
245+ return false ;
246+ return a == other.a ;
247+ }
248+ };
132249
133- T greater_smaller{{2 , 2 }, {3 , 3 }};
134- T lesser_bigger{{0 , 2 }, {3 , 3 }, {0 , 0 }};
250+ using T = custom;
251+
252+ vec_list<inplace_vector<custom, 4 >> list{
253+ .empty {},
254+ .base {T{1 }, T{2 }, T{3 }},
255+ .copy {T{1 }, T{2 }, T{3 }},
256+ .greater {T{4 }, T{5 }, T{6 }},
257+ .lesser {T{0 }, T{0 }, T{0 }},
258+ .bigger {T{1 }, T{2 }, T{3 }, T{0 }},
259+ .smaller {T{1 }, T{2 }},
260+ .greater_smaller {T{2 }, T{2 }},
261+ .lesser_bigger {T{0 }, T{2 }, T{3 }, T{4 }},
262+ };
135263
136- EXPECT_TRUE ((empty <=> empty) == 0 );
137- EXPECT_TRUE ((base <=> copy) == 0 );
264+ runtests (list);
138265
139- EXPECT_TRUE ((base <=> greater) < 0 );
140- EXPECT_TRUE ((base <=> lesser) > 0 );
266+ T t1{-1 };
267+ T t2 = t1;
268+ EXPECT_EQ (t1 <=> t2, std::partial_ordering::unordered);
141269
142- EXPECT_TRUE ((base <=> bigger) < 0 ) ;
143- EXPECT_TRUE ((base <=> smaller) > 0 ) ;
270+ inplace_vector<T, 4 > v1{t1} ;
271+ inplace_vector<T, 4 > v2{t2} ;
144272
145- EXPECT_TRUE ((base <=> greater_smaller) < 0 );
146- EXPECT_TRUE ((base <=> lesser_bigger) > 0 );
273+ EXPECT_EQ (v1 <=> v2, std::partial_ordering::unordered);
274+ EXPECT_FALSE (v1 == v2);
275+ EXPECT_FALSE (v1 < v2);
276+ EXPECT_FALSE (v1 > v2);
277+ EXPECT_FALSE (v1 >= v2);
278+ EXPECT_FALSE (v1 <= v2);
147279}
148280
149281TEST (Compare, threeway_uncomparable) {
@@ -172,10 +304,11 @@ TEST(Compare, threeway_uncomparable) {
172304 constexpr auto operator <=>(const uncomparable3 &) const {
173305 return std::partial_ordering::unordered;
174306 }
307+ constexpr bool operator ==(const uncomparable3 &) const = delete ;
175308 };
176309
177310 static_assert (!std::three_way_comparable<uncomparable3>);
178- static_assert (has_threeway<uncomparable3>); // has op but returns unordered
311+ static_assert (has_threeway<uncomparable3>); // has <=> but no == operator
179312 static_assert (!std::three_way_comparable<inplace_vector<uncomparable3, 4 >>);
180313 static_assert (!has_threeway<inplace_vector<uncomparable3, 4 >>);
181314}
0 commit comments