• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3 // |  |  |__   |  |  | | | |  version 3.11.2
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 // cmake/test.cmake selects the C++ standard versions with which to build a
10 // unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
11 // When using macros that are only defined for particular versions of the standard
12 // (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
13 // version macro in a comment close by, like this:
14 // JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
15 
16 #include "doctest_compatibility.h"
17 
18 #include <nlohmann/json.hpp>
19 using nlohmann::json;
20 
21 #if JSON_HAS_RANGES
22     #include <algorithm>
23     #include <ranges>
24 #endif
25 
26 TEST_CASE("iterators 2")
27 {
28     SECTION("iterator comparisons")
29     {
30         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
31 
32         for (json& j : j_values)
33         {
34             auto it1 = j.begin();
35             auto it2 = j.begin();
36             auto it3 = j.begin();
37             ++it2;
38             ++it3;
39             ++it3;
40             auto it1_c = j.cbegin();
41             auto it2_c = j.cbegin();
42             auto it3_c = j.cbegin();
43             ++it2_c;
44             ++it3_c;
45             ++it3_c;
46 
47             // comparison: equal
48             {
49                 CHECK(it1 == it1);
50                 CHECK(!(it1 == it2));
51                 CHECK(!(it1 == it3));
52                 CHECK(!(it2 == it3));
53                 CHECK(it1_c == it1_c);
54                 CHECK(!(it1_c == it2_c));
55                 CHECK(!(it1_c == it3_c));
56                 CHECK(!(it2_c == it3_c));
57             }
58 
59             // comparison: not equal
60             {
61                 // check definition
62                 CHECK( (it1 != it1) == !(it1 == it1) );
63                 CHECK( (it1 != it2) == !(it1 == it2) );
64                 CHECK( (it1 != it3) == !(it1 == it3) );
65                 CHECK( (it2 != it3) == !(it2 == it3) );
66                 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
67                 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
68                 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
69                 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
70             }
71 
72             // comparison: smaller
73             {
74                 if (j.type() == json::value_t::object)
75                 {
76 #if JSON_DIAGNOSTICS
77                     CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
78                     CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
79                     CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
80                     CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
81                     CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
82                     CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
83                     CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
84                     CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
85 #else
86                     CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
87                     CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
88                     CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
89                     CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
90                     CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
91                     CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
92                     CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
93                     CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
94 #endif
95                 }
96                 else
97                 {
98                     CHECK(!(it1 < it1));
99                     CHECK(it1 < it2);
100                     CHECK(it1 < it3);
101                     CHECK(it2 < it3);
102                     CHECK(!(it1_c < it1_c));
103                     CHECK(it1_c < it2_c);
104                     CHECK(it1_c < it3_c);
105                     CHECK(it2_c < it3_c);
106                 }
107             }
108 
109             // comparison: less than or equal
110             {
111                 if (j.type() == json::value_t::object)
112                 {
113 #if JSON_DIAGNOSTICS
114                     CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
115                     CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
116                     CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
117                     CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
118                     CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
119                     CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
120                     CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
121                     CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
122 #else
123                     CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
124                     CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
125                     CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
126                     CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
127                     CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
128                     CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
129                     CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
130                     CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
131 #endif
132                 }
133                 else
134                 {
135                     // check definition
136                     CHECK( (it1 <= it1) == !(it1 < it1) );
137                     CHECK( (it1 <= it2) == !(it2 < it1) );
138                     CHECK( (it1 <= it3) == !(it3 < it1) );
139                     CHECK( (it2 <= it3) == !(it3 < it2) );
140                     CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
141                     CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
142                     CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
143                     CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
144                 }
145             }
146 
147             // comparison: greater than
148             {
149                 if (j.type() == json::value_t::object)
150                 {
151 #if JSON_DIAGNOSTICS
152                     CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
153                     CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
154                     CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
155                     CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
156                     CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
157                     CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
158                     CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
159                     CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
160 #else
161                     CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
162                     CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
163                     CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
164                     CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
165                     CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
166                     CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
167                     CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
168                     CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
169 #endif
170                 }
171                 else
172                 {
173                     // check definition
174                     CHECK( (it1 > it1) == (it1 < it1) );
175                     CHECK( (it1 > it2) == (it2 < it1) );
176                     CHECK( (it1 > it3) == (it3 < it1) );
177                     CHECK( (it2 > it3) == (it3 < it2) );
178                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
179                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
180                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
181                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
182                 }
183             }
184 
185             // comparison: greater than or equal
186             {
187                 if (j.type() == json::value_t::object)
188                 {
189 #if JSON_DIAGNOSTICS
190                     CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
191                     CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
192                     CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
193                     CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
194                     CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
195                     CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
196                     CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
197                     CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
198 #else
199                     CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
200                     CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
201                     CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
202                     CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
203                     CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
204                     CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
205                     CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
206                     CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
207 #endif
208                 }
209                 else
210                 {
211                     // check definition
212                     CHECK( (it1 >= it1) == !(it1 < it1) );
213                     CHECK( (it1 >= it2) == !(it1 < it2) );
214                     CHECK( (it1 >= it3) == !(it1 < it3) );
215                     CHECK( (it2 >= it3) == !(it2 < it3) );
216                     CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
217                     CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
218                     CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
219                     CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
220                 }
221             }
222         }
223 
224         // check exceptions if different objects are compared
225         for (auto j : j_values)
226         {
227             for (auto k : j_values)
228             {
229                 if (j != k)
230                 {
231 #if JSON_DIAGNOSTICS
232                     // the output differs in each loop, so we cannot fix a string for the expected exception
233 #else
234                     CHECK_THROWS_WITH_AS(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
235                     CHECK_THROWS_WITH_AS(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
236                     CHECK_THROWS_WITH_AS(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
237                     CHECK_THROWS_WITH_AS(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
238 #endif
239                 }
240             }
241         }
242     }
243 
244     SECTION("iterator arithmetic")
245     {
246         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
247         json j_array = {1, 2, 3, 4, 5, 6};
248         json j_null = nullptr;
249         json j_value = 42;
250 
251         SECTION("addition and subtraction")
252         {
253             SECTION("object")
254             {
255                 {
256                     auto it = j_object.begin();
257                     CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
258                 }
259                 {
260                     auto it = j_object.cbegin();
261                     CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
262                 }
263                 {
264                     auto it = j_object.begin();
265                     CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
266                 }
267                 {
268                     auto it = j_object.cbegin();
269                     CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
270                 }
271                 {
272                     auto it = j_object.begin();
273                     CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
274                 }
275                 {
276                     auto it = j_object.cbegin();
277                     CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
278                 }
279                 {
280                     auto it = j_object.begin();
281                     CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
282                 }
283                 {
284                     auto it = j_object.cbegin();
285                     CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
286                 }
287                 {
288                     auto it = j_object.begin();
289                     CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
290                 }
291                 {
292                     auto it = j_object.cbegin();
293                     CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
294                 }
295                 {
296                     auto it = j_object.begin();
297                     CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
298                 }
299                 {
300                     auto it = j_object.cbegin();
301                     CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
302                 }
303             }
304 
305             SECTION("array")
306             {
307                 {
308                     auto it = j_array.begin();
309                     it += 3;
310                     CHECK((j_array.begin() + 3) == it);
311                     CHECK((3 + j_array.begin()) == it);
312                     CHECK((it - 3) == j_array.begin());
313                     CHECK((it - j_array.begin()) == 3);
314                     CHECK(*it == json(4));
315                     it -= 2;
316                     CHECK(*it == json(2));
317                 }
318                 {
319                     auto it = j_array.cbegin();
320                     it += 3;
321                     CHECK((j_array.cbegin() + 3) == it);
322                     CHECK((3 + j_array.cbegin()) == it);
323                     CHECK((it - 3) == j_array.cbegin());
324                     CHECK((it - j_array.cbegin()) == 3);
325                     CHECK(*it == json(4));
326                     it -= 2;
327                     CHECK(*it == json(2));
328                 }
329             }
330 
331             SECTION("null")
332             {
333                 {
334                     auto it = j_null.begin();
335                     it += 3;
336                     CHECK((j_null.begin() + 3) == it);
337                     CHECK((3 + j_null.begin()) == it);
338                     CHECK((it - 3) == j_null.begin());
339                     CHECK((it - j_null.begin()) == 3);
340                     CHECK(it != j_null.end());
341                     it -= 3;
342                     CHECK(it == j_null.end());
343                 }
344                 {
345                     auto it = j_null.cbegin();
346                     it += 3;
347                     CHECK((j_null.cbegin() + 3) == it);
348                     CHECK((3 + j_null.cbegin()) == it);
349                     CHECK((it - 3) == j_null.cbegin());
350                     CHECK((it - j_null.cbegin()) == 3);
351                     CHECK(it != j_null.cend());
352                     it -= 3;
353                     CHECK(it == j_null.cend());
354                 }
355             }
356 
357             SECTION("value")
358             {
359                 {
360                     auto it = j_value.begin();
361                     it += 3;
362                     CHECK((j_value.begin() + 3) == it);
363                     CHECK((3 + j_value.begin()) == it);
364                     CHECK((it - 3) == j_value.begin());
365                     CHECK((it - j_value.begin()) == 3);
366                     CHECK(it != j_value.end());
367                     it -= 3;
368                     CHECK(*it == json(42));
369                 }
370                 {
371                     auto it = j_value.cbegin();
372                     it += 3;
373                     CHECK((j_value.cbegin() + 3) == it);
374                     CHECK((3 + j_value.cbegin()) == it);
375                     CHECK((it - 3) == j_value.cbegin());
376                     CHECK((it - j_value.cbegin()) == 3);
377                     CHECK(it != j_value.cend());
378                     it -= 3;
379                     CHECK(*it == json(42));
380                 }
381             }
382         }
383 
384         SECTION("subscript operator")
385         {
386             SECTION("object")
387             {
388                 {
389                     auto it = j_object.begin();
390                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
391                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
392                 }
393                 {
394                     auto it = j_object.cbegin();
395                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
396                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&);
397                 }
398             }
399 
400             SECTION("array")
401             {
402                 {
403                     auto it = j_array.begin();
404                     CHECK(it[0] == json(1));
405                     CHECK(it[1] == json(2));
406                     CHECK(it[2] == json(3));
407                     CHECK(it[3] == json(4));
408                     CHECK(it[4] == json(5));
409                     CHECK(it[5] == json(6));
410                 }
411                 {
412                     auto it = j_array.cbegin();
413                     CHECK(it[0] == json(1));
414                     CHECK(it[1] == json(2));
415                     CHECK(it[2] == json(3));
416                     CHECK(it[3] == json(4));
417                     CHECK(it[4] == json(5));
418                     CHECK(it[5] == json(6));
419                 }
420             }
421 
422             SECTION("null")
423             {
424                 {
425                     auto it = j_null.begin();
426                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
427                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
428                 }
429                 {
430                     auto it = j_null.cbegin();
431                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
432                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
433                 }
434             }
435 
436             SECTION("value")
437             {
438                 {
439                     auto it = j_value.begin();
440                     CHECK(it[0] == json(42));
441                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
442                 }
443                 {
444                     auto it = j_value.cbegin();
445                     CHECK(it[0] == json(42));
446                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
447                 }
448             }
449         }
450     }
451 
452     SECTION("reverse iterator comparisons")
453     {
454         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
455 
456         for (json& j : j_values)
457         {
458             auto it1 = j.rbegin();
459             auto it2 = j.rbegin();
460             auto it3 = j.rbegin();
461             ++it2;
462             ++it3;
463             ++it3;
464             auto it1_c = j.crbegin();
465             auto it2_c = j.crbegin();
466             auto it3_c = j.crbegin();
467             ++it2_c;
468             ++it3_c;
469             ++it3_c;
470 
471             // comparison: equal
472             {
473                 CHECK(it1 == it1);
474                 CHECK(!(it1 == it2));
475                 CHECK(!(it1 == it3));
476                 CHECK(!(it2 == it3));
477                 CHECK(it1_c == it1_c);
478                 CHECK(!(it1_c == it2_c));
479                 CHECK(!(it1_c == it3_c));
480                 CHECK(!(it2_c == it3_c));
481             }
482 
483             // comparison: not equal
484             {
485                 // check definition
486                 CHECK( (it1 != it1) == !(it1 == it1) );
487                 CHECK( (it1 != it2) == !(it1 == it2) );
488                 CHECK( (it1 != it3) == !(it1 == it3) );
489                 CHECK( (it2 != it3) == !(it2 == it3) );
490                 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
491                 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
492                 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
493                 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
494             }
495 
496             // comparison: smaller
497             {
498                 if (j.type() == json::value_t::object)
499                 {
500 #if JSON_DIAGNOSTICS
501                     CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
502                     CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
503                     CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
504                     CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
505                     CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
506                     CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
507                     CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
508                     CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
509 #else
510                     CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
511                     CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
512                     CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
513                     CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
514                     CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
515                     CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
516                     CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
517                     CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
518 #endif
519                 }
520                 else
521                 {
522                     CHECK(!(it1 < it1));
523                     CHECK(it1 < it2);
524                     CHECK(it1 < it3);
525                     CHECK(it2 < it3);
526                     CHECK(!(it1_c < it1_c));
527                     CHECK(it1_c < it2_c);
528                     CHECK(it1_c < it3_c);
529                     CHECK(it2_c < it3_c);
530                 }
531             }
532 
533             // comparison: less than or equal
534             {
535                 if (j.type() == json::value_t::object)
536                 {
537 #if JSON_DIAGNOSTICS
538                     CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
539                     CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
540                     CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
541                     CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
542                     CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
543                     CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
544                     CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
545                     CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
546 #else
547                     CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
548                     CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
549                     CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
550                     CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
551                     CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
552                     CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
553                     CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
554                     CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
555 #endif
556                 }
557                 else
558                 {
559                     // check definition
560                     CHECK( (it1 <= it1) == !(it1 < it1) );
561                     CHECK( (it1 <= it2) == !(it2 < it1) );
562                     CHECK( (it1 <= it3) == !(it3 < it1) );
563                     CHECK( (it2 <= it3) == !(it3 < it2) );
564                     CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
565                     CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
566                     CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
567                     CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
568                 }
569             }
570 
571             // comparison: greater than
572             {
573                 if (j.type() == json::value_t::object)
574                 {
575 #if JSON_DIAGNOSTICS
576                     CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
577                     CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
578                     CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
579                     CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
580                     CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
581                     CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
582                     CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
583                     CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
584 #else
585                     CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
586                     CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
587                     CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
588                     CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
589                     CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
590                     CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
591                     CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
592                     CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
593 #endif
594                 }
595                 else
596                 {
597                     // check definition
598                     CHECK( (it1 > it1) == (it1 < it1) );
599                     CHECK( (it1 > it2) == (it2 < it1) );
600                     CHECK( (it1 > it3) == (it3 < it1) );
601                     CHECK( (it2 > it3) == (it3 < it2) );
602                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
603                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
604                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
605                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
606                 }
607             }
608 
609             // comparison: greater than or equal
610             {
611                 if (j.type() == json::value_t::object)
612                 {
613 #if JSON_DIAGNOSTICS
614                     CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
615                     CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
616                     CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
617                     CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
618                     CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
619                     CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
620                     CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
621                     CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
622 #else
623                     CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
624                     CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
625                     CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
626                     CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
627                     CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
628                     CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
629                     CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
630                     CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
631 #endif
632                 }
633                 else
634                 {
635                     // check definition
636                     CHECK( (it1 >= it1) == !(it1 < it1) );
637                     CHECK( (it1 >= it2) == !(it1 < it2) );
638                     CHECK( (it1 >= it3) == !(it1 < it3) );
639                     CHECK( (it2 >= it3) == !(it2 < it3) );
640                     CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
641                     CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
642                     CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
643                     CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
644                 }
645             }
646         }
647 
648         // check exceptions if different objects are compared
649         for (auto j : j_values)
650         {
651             for (auto k : j_values)
652             {
653                 if (j != k)
654                 {
655 #if JSON_DIAGNOSTICS
656                     // the output differs in each loop, so we cannot fix a string for the expected exception
657 #else
658                     CHECK_THROWS_WITH_AS(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
659                     CHECK_THROWS_WITH_AS(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
660                     CHECK_THROWS_WITH_AS(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
661                     CHECK_THROWS_WITH_AS(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
662 #endif
663                 }
664             }
665         }
666     }
667 
668     SECTION("reverse iterator arithmetic")
669     {
670         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
671         json j_array = {1, 2, 3, 4, 5, 6};
672         json j_null = nullptr;
673         json j_value = 42;
674 
675         SECTION("addition and subtraction")
676         {
677             SECTION("object")
678             {
679                 {
680                     auto it = j_object.rbegin();
681                     CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
682                 }
683                 {
684                     auto it = j_object.crbegin();
685                     CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
686                 }
687                 {
688                     auto it = j_object.rbegin();
689                     CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
690                 }
691                 {
692                     auto it = j_object.crbegin();
693                     CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
694                 }
695                 {
696                     auto it = j_object.rbegin();
697                     CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
698                 }
699                 {
700                     auto it = j_object.crbegin();
701                     CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
702                 }
703                 {
704                     auto it = j_object.rbegin();
705                     CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
706                 }
707                 {
708                     auto it = j_object.crbegin();
709                     CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
710                 }
711                 {
712                     auto it = j_object.rbegin();
713                     CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
714                 }
715                 {
716                     auto it = j_object.crbegin();
717                     CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
718                 }
719                 {
720                     auto it = j_object.rbegin();
721                     CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
722                 }
723                 {
724                     auto it = j_object.crbegin();
725                     CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
726                 }
727             }
728 
729             SECTION("array")
730             {
731                 {
732                     auto it = j_array.rbegin();
733                     it += 3;
734                     CHECK((j_array.rbegin() + 3) == it);
735                     CHECK(json::reverse_iterator(3 + j_array.rbegin()) == it);
736                     CHECK((it - 3) == j_array.rbegin());
737                     CHECK((it - j_array.rbegin()) == 3);
738                     CHECK(*it == json(3));
739                     it -= 2;
740                     CHECK(*it == json(5));
741                 }
742                 {
743                     auto it = j_array.crbegin();
744                     it += 3;
745                     CHECK((j_array.crbegin() + 3) == it);
746                     CHECK(json::const_reverse_iterator(3 + j_array.crbegin()) == it);
747                     CHECK((it - 3) == j_array.crbegin());
748                     CHECK((it - j_array.crbegin()) == 3);
749                     CHECK(*it == json(3));
750                     it -= 2;
751                     CHECK(*it == json(5));
752                 }
753             }
754 
755             SECTION("null")
756             {
757                 {
758                     auto it = j_null.rbegin();
759                     it += 3;
760                     CHECK((j_null.rbegin() + 3) == it);
761                     CHECK(json::reverse_iterator(3 + j_null.rbegin()) == it);
762                     CHECK((it - 3) == j_null.rbegin());
763                     CHECK((it - j_null.rbegin()) == 3);
764                     CHECK(it != j_null.rend());
765                     it -= 3;
766                     CHECK(it == j_null.rend());
767                 }
768                 {
769                     auto it = j_null.crbegin();
770                     it += 3;
771                     CHECK((j_null.crbegin() + 3) == it);
772                     CHECK(json::const_reverse_iterator(3 + j_null.crbegin()) == it);
773                     CHECK((it - 3) == j_null.crbegin());
774                     CHECK((it - j_null.crbegin()) == 3);
775                     CHECK(it != j_null.crend());
776                     it -= 3;
777                     CHECK(it == j_null.crend());
778                 }
779             }
780 
781             SECTION("value")
782             {
783                 {
784                     auto it = j_value.rbegin();
785                     it += 3;
786                     CHECK((j_value.rbegin() + 3) == it);
787                     CHECK(json::reverse_iterator(3 + j_value.rbegin()) == it);
788                     CHECK((it - 3) == j_value.rbegin());
789                     CHECK((it - j_value.rbegin()) == 3);
790                     CHECK(it != j_value.rend());
791                     it -= 3;
792                     CHECK(*it == json(42));
793                 }
794                 {
795                     auto it = j_value.crbegin();
796                     it += 3;
797                     CHECK((j_value.crbegin() + 3) == it);
798                     CHECK(json::const_reverse_iterator(3 + j_value.crbegin()) == it);
799                     CHECK((it - 3) == j_value.crbegin());
800                     CHECK((it - j_value.crbegin()) == 3);
801                     CHECK(it != j_value.crend());
802                     it -= 3;
803                     CHECK(*it == json(42));
804                 }
805             }
806         }
807 
808         SECTION("subscript operator")
809         {
810             SECTION("object")
811             {
812                 {
813                     auto it = j_object.rbegin();
814                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
815                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
816                 }
817                 {
818                     auto it = j_object.crbegin();
819                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
820                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
821                 }
822             }
823 
824             SECTION("array")
825             {
826                 {
827                     auto it = j_array.rbegin();
828                     CHECK(it[0] == json(6));
829                     CHECK(it[1] == json(5));
830                     CHECK(it[2] == json(4));
831                     CHECK(it[3] == json(3));
832                     CHECK(it[4] == json(2));
833                     CHECK(it[5] == json(1));
834                 }
835                 {
836                     auto it = j_array.crbegin();
837                     CHECK(it[0] == json(6));
838                     CHECK(it[1] == json(5));
839                     CHECK(it[2] == json(4));
840                     CHECK(it[3] == json(3));
841                     CHECK(it[4] == json(2));
842                     CHECK(it[5] == json(1));
843                 }
844             }
845 
846             SECTION("null")
847             {
848                 {
849                     auto it = j_null.rbegin();
850                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
851                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
852                 }
853                 {
854                     auto it = j_null.crbegin();
855                     CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
856                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
857                 }
858             }
859 
860             SECTION("value")
861             {
862                 {
863                     auto it = j_value.rbegin();
864                     CHECK(it[0] == json(42));
865                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
866                 }
867                 {
868                     auto it = j_value.crbegin();
869                     CHECK(it[0] == json(42));
870                     CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
871                 }
872             }
873         }
874     }
875 
876 
877 #if JSON_HAS_RANGES
878     // JSON_HAS_CPP_20 (do not remove; see note at top of file)
879     SECTION("ranges")
880     {
881         SECTION("concepts")
882         {
883             using nlohmann::detail::iteration_proxy_value;
884             CHECK(std::bidirectional_iterator<json::iterator>);
885             CHECK(std::input_iterator<iteration_proxy_value<json::iterator>>);
886 
887             CHECK(std::is_same<json::iterator, std::ranges::iterator_t<json>>::value);
888             CHECK(std::ranges::bidirectional_range<json>);
889 
890             using nlohmann::detail::iteration_proxy;
891             using items_type = decltype(std::declval<json&>().items());
892             CHECK(std::is_same<items_type, iteration_proxy<json::iterator>>::value);
893             CHECK(std::is_same<iteration_proxy_value<json::iterator>, std::ranges::iterator_t<items_type>>::value);
894             CHECK(std::ranges::input_range<items_type>);
895         }
896 
897         // libstdc++ algorithms don't work with Clang 15 (04/2022)
898 #if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__))
899         SECTION("algorithms")
900         {
901             SECTION("copy")
902             {
903                 json j{"foo", "bar"};
904                 auto j_copied = json::array();
905 
906                 std::ranges::copy(j, std::back_inserter(j_copied));
907 
908                 CHECK(j == j_copied);
909             }
910 
911             SECTION("find_if")
912             {
913                 json j{1, 3, 2, 4};
914                 auto j_even = json::array();
915 
916 #if JSON_USE_IMPLICIT_CONVERSIONS
917                 auto it = std::ranges::find_if(j, [](int v) noexcept
__anon1ab329320102(int v) 918                 {
919                     return (v % 2) == 0;
920                 });
921 #else
922                 auto it = std::ranges::find_if(j, [](const json & j) noexcept
__anon1ab329320202(const json & j) 923                 {
924                     int v;
925                     j.get_to(v);
926                     return (v % 2) == 0;
927                 });
928 #endif
929 
930                 CHECK(*it == 2);
931             }
932         }
933 #endif
934 
935         // libstdc++ views don't work with Clang 15 (04/2022)
936         // libc++ hides limited ranges implementation behind guard macro
937 #if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
938         SECTION("views")
939         {
940             SECTION("reverse")
941             {
942                 json j{1, 2, 3, 4, 5};
943                 json j_expected{5, 4, 3, 2, 1};
944 
945                 auto reversed = j | std::views::reverse;
946                 CHECK(reversed == j_expected);
947             }
948 
949             SECTION("transform")
950             {
951                 json j
952                 {
953                     { "a_key", "a_value"},
954                     { "b_key", "b_value"},
955                     { "c_key", "c_value"},
956                 };
957                 json j_expected{"a_key", "b_key", "c_key"};
958 
959                 auto transformed = j.items() | std::views::transform([](const auto & item)
__anon1ab329320302(const auto & item) 960                 {
961                     return item.key();
962                 });
963                 auto j_transformed = json::array();
964                 std::ranges::copy(transformed, std::back_inserter(j_transformed));
965 
966                 CHECK(j_transformed == j_expected);
967             }
968         }
969 #endif
970     }
971 #endif
972 }
973