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 #include "doctest_compatibility.h"
10 
11 #include <nlohmann/json.hpp>
12 using nlohmann::json;
13 
14 TEST_CASE("concepts")
15 {
16     SECTION("container requirements for json")
17     {
18         // X: container class: json
19         // T: type of objects: json
20         // a, b: values of type X: json
21 
22         // TABLE 96 - Container Requirements
23 
24         // X::value_type must return T
25         CHECK((std::is_same<json::value_type, json>::value));
26 
27         // X::reference must return lvalue of T
28         CHECK((std::is_same<json::reference, json&>::value));
29 
30         // X::const_reference must return const lvalue of T
31         CHECK((std::is_same<json::const_reference, const json&>::value));
32 
33         // X::iterator must return iterator whose value_type is T
34         CHECK((std::is_same<json::iterator::value_type, json>::value));
35         // X::iterator must meet the forward iterator requirements
36         CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
37         // X::iterator must be convertible to X::const_iterator
38         CHECK((std::is_convertible<json::iterator, json::const_iterator>::value));
39 
40         // X::const_iterator must return iterator whose value_type is T
41         CHECK((std::is_same<json::const_iterator::value_type, json>::value));
42         // X::const_iterator must meet the forward iterator requirements
43         CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
44 
45         // X::difference_type must return a signed integer
46         CHECK((std::is_signed<json::difference_type>::value));
47         // X::difference_type must be identical to X::iterator::difference_type
48         CHECK((std::is_same<json::difference_type, json::iterator::difference_type>::value));
49         // X::difference_type must be identical to X::const_iterator::difference_type
50         CHECK((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
51 
52         // X::size_type must return an unsigned integer
53         CHECK((std::is_unsigned<json::size_type>::value));
54         // X::size_type can represent any non-negative value of X::difference_type
55         CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
56               (std::numeric_limits<json::size_type>::max)());
57 
58         // the expression "X u" has the post-condition "u.empty()"
59         {
60             json u;
61             CHECK(u.empty());
62         }
63 
64         // the expression "X()" has the post-condition "X().empty()"
65         CHECK(json().empty());
66     }
67 
68     SECTION("class json")
69     {
70         SECTION("DefaultConstructible")
71         {
72             CHECK(std::is_nothrow_default_constructible<json>::value);
73         }
74 
75         SECTION("MoveConstructible")
76         {
77             CHECK(std::is_move_constructible<json>::value);
78             CHECK(std::is_nothrow_move_constructible<json>::value);
79         }
80 
81         SECTION("CopyConstructible")
82         {
83             CHECK(std::is_copy_constructible<json>::value);
84         }
85 
86         SECTION("MoveAssignable")
87         {
88             CHECK(std::is_nothrow_move_assignable<json>::value);
89         }
90 
91         SECTION("CopyAssignable")
92         {
93             CHECK(std::is_copy_assignable<json>::value);
94         }
95 
96         SECTION("Destructible")
97         {
98             CHECK(std::is_nothrow_destructible<json>::value);
99         }
100 
101         SECTION("StandardLayoutType")
102         {
103             CHECK(std::is_standard_layout<json>::value);
104         }
105     }
106 
107     SECTION("class iterator")
108     {
109         SECTION("CopyConstructible")
110         {
111             CHECK(std::is_nothrow_copy_constructible<json::iterator>::value);
112             CHECK(std::is_nothrow_copy_constructible<json::const_iterator>::value);
113         }
114 
115         SECTION("CopyAssignable")
116         {
117             // STL iterators used by json::iterator don't pass this test in Debug mode
118 #if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
119             CHECK(std::is_nothrow_copy_assignable<json::iterator>::value);
120             CHECK(std::is_nothrow_copy_assignable<json::const_iterator>::value);
121 #endif
122         }
123 
124         SECTION("Destructible")
125         {
126             CHECK(std::is_nothrow_destructible<json::iterator>::value);
127             CHECK(std::is_nothrow_destructible<json::const_iterator>::value);
128         }
129 
130         SECTION("Swappable")
131         {
132             {
133                 json j {1, 2, 3};
134                 json::iterator it1 = j.begin();
135                 json::iterator it2 = j.end();
136                 swap(it1, it2);
137                 CHECK(it1 == j.end());
138                 CHECK(it2 == j.begin());
139             }
140             {
141                 json j {1, 2, 3};
142                 json::const_iterator it1 = j.cbegin();
143                 json::const_iterator it2 = j.cend();
144                 swap(it1, it2);
145                 CHECK(it1 == j.end());
146                 CHECK(it2 == j.begin());
147             }
148         }
149     }
150 }
151