Skip to content

Commit 5352856

Browse files
Implement support for string_view (attempt no. 3) (#3423)
* Add key_compare member to ordered_map * Replace == with key_compare in ordered_map * Expose the actual comparison function used by object_t nlohmann::ordered_map uses a different comparison function than the one provided via template parameter. * Introduce a type trait to detect if object_t has a key_compare member. * Rename object_comparator_t to default_object_comparator_t. * Add object_comparator_t to be conditionally defined as object_t::key_compare, if available, or default_object_comparator_t otherwise. * Update the documentation accordingly. Co-authored-by: Niels Lohmann <[email protected]> * Add type traits to check if a type is usable as object key Add type trait to check: * if a type is a specialization of a template. * if a type is a json_pointer. * if a type is a basic_json::{const_,}iterator. * if two types are comparable using a given comparison functor. * if a type is comparable to basic_json::object_t::key_type. * if a type has a member type is_transparent. * if a type is usable as object key. * if a type has an erase() function accepting a given KeyType. Co-authored-by: Niels Lohmann <[email protected]> * Rework basic_json element access to accept more key types Rework basic_json element access member functions and operators to accept any type that meets the requirements defined by type trait detail::is_usable_as_key_type. Member functions and operators: * at() * operator[] * value() * erase() * find() * count() * contains() Update documentation to reflect these changes. Add unit tests to excercise the new functions using std::string_view. Co-authored-by: Niels Lohmann <[email protected]> Co-authored-by: Niels Lohmann <[email protected]>
1 parent ee51661 commit 5352856

26 files changed

+1512
-300
lines changed

doc/mkdocs/docs/api/basic_json/at.md

+30-11
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,28 @@ reference at(const typename object_t::key_type& key);
1010
const_reference at(const typename object_t::key_type& key) const;
1111

1212
// (3)
13+
template<typename KeyType>
14+
reference at(KeyType&& key);
15+
template<typename KeyType>
16+
const_reference at(KeyType&& key) const;
17+
18+
// (4)
1319
reference at(const json_pointer& ptr);
1420
const_reference at(const json_pointer& ptr) const;
1521
```
1622
1723
1. Returns a reference to the array element at specified location `idx`, with bounds checking.
18-
2. Returns a reference to the object element at with specified key `key`, with bounds checking.
19-
3. Returns a reference to the element at with specified JSON pointer `ptr`, with bounds checking.
24+
2. Returns a reference to the object element with specified key `key`, with bounds checking.
25+
3. See 2. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
26+
`#!cpp typename object_comparator_t::is_transparent` denotes a type.
27+
4. Returns a reference to the element at specified JSON pointer `ptr`, with bounds checking.
28+
29+
## Template parameters
30+
31+
`KeyType`
32+
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
33+
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
34+
This can also be a string view (C++17).
2035
2136
## Parameters
2237
@@ -25,15 +40,16 @@ const_reference at(const json_pointer& ptr) const;
2540
2641
`key` (in)
2742
: object key of the elements to access
28-
43+
2944
`ptr` (in)
3045
: JSON pointer to the desired element
31-
46+
3247
## Return value
3348
3449
1. reference to the element at index `idx`
3550
2. reference to the element at key `key`
36-
3. reference to the element pointed to by `ptr`
51+
3. reference to the element at key `key`
52+
4. reference to the element pointed to by `ptr`
3753
3854
## Exception safety
3955
@@ -51,7 +67,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
5167
in this case, calling `at` with a key makes no sense. See example below.
5268
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if the key `key` is not
5369
stored in the object; that is, `find(key) == end()`. See example below.
54-
3. The function can throw the following exceptions:
70+
3. See 2.
71+
4. The function can throw the following exceptions:
5572
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed
5673
JSON pointer `ptr` begins with '0'. See example below.
5774
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed
@@ -68,9 +85,10 @@ Strong exception safety: if an exception occurs, the original value stays intact
6885
6986
## Complexity
7087
71-
1. Constant
88+
1. Constant.
7289
2. Logarithmic in the size of the container.
73-
3. Constant
90+
3. Logarithmic in the size of the container.
91+
4. Logarithmic in the size of the container.
7492
7593
## Examples
7694
@@ -134,7 +152,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
134152
--8<-- "examples/at__object_t_key_type_const.output"
135153
```
136154
137-
??? example "Example (3) access specified element via JSON Pointer"
155+
??? example "Example (4) access specified element via JSON Pointer"
138156
139157
The example below shows how object elements can be read and written using `at()`. It also demonstrates the different
140158
exceptions that can be thrown.
@@ -149,7 +167,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
149167
--8<-- "examples/at_json_pointer.output"
150168
```
151169
152-
??? example "Example (3) access specified element via JSON Pointer"
170+
??? example "Example (4) access specified element via JSON Pointer"
153171
154172
The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions
155173
that can be thrown.
@@ -173,4 +191,5 @@ Strong exception safety: if an exception occurs, the original value stays intact
173191
174192
1. Added in version 1.0.0.
175193
2. Added in version 1.0.0.
176-
3. Added in version 2.0.0.
194+
3. Added in version 3.11.0.
195+
4. Added in version 2.0.0.

doc/mkdocs/docs/api/basic_json/basic_json.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,16 @@ basic_json(basic_json&& other) noexcept;
201201
202202
## Exceptions
203203
204-
1. /
204+
1. (none)
205205
2. The function does not throw exceptions.
206-
3. /
207-
4. /
206+
3. (none)
207+
4. (none)
208208
5. The function can throw the following exceptions:
209209
- Throws [`type_error.301`](../../home/exceptions.md#jsonexceptiontype_error301) if `type_deduction` is
210210
`#!cpp false`, `manual_type` is `value_t::object`, but `init` contains an element which is not a pair whose first
211211
element is a string. In this case, the constructor could not create an object. If `type_deduction` would have been
212212
`#!cpp true`, an array would have been created. See `object(initializer_list_t)` for an example.
213-
6. /
213+
6. (none)
214214
7. The function can throw the following exceptions:
215215
- Throws [`invalid_iterator.201`](../../home/exceptions.md#jsonexceptioninvalid_iterator201) if iterators `first`
216216
and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range
@@ -220,7 +220,7 @@ basic_json(basic_json&& other) noexcept;
220220
element anymore. In this case, the range `[first, last)` is undefined. See example code below.
221221
- Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first`
222222
and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined.
223-
8. /
223+
8. (none)
224224
9. The function does not throw exceptions.
225225
226226
## Complexity

doc/mkdocs/docs/api/basic_json/contains.md

+21-11
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@
22

33
```cpp
44
// (1)
5-
template<typename KeyT>
6-
bool contains(KeyT && key) const;
5+
bool contains(const typename object_t::key_type& key) const;
76

87
// (2)
8+
template<typename KeyType>
9+
bool contains(KeyType&& key) const;
10+
11+
// (3)
912
bool contains(const json_pointer& ptr) const;
1013
```
1114
12-
1. Check whether an element exists in a JSON object with key equivalent to `key`. If the element is not found or the
15+
1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the
1316
JSON value is not an object, `#!cpp false` is returned.
14-
2. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value.
17+
2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
18+
`#!cpp typename object_comparator_t::is_transparent` denotes a type.
19+
3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value.
1520
1621
## Template parameters
1722
18-
`KeyT`
19-
: A type for an object key other than `basic_json::json_pointer`.
23+
`KeyType`
24+
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
25+
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
26+
This can also be a string view (C++17).
2027
2128
## Parameters
2229
@@ -30,7 +37,8 @@ bool contains(const json_pointer& ptr) const;
3037
3138
1. `#!cpp true` if an element with specified `key` exists. If no such element with such key is found or the JSON value
3239
is not an object, `#!cpp false` is returned.
33-
2. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise.
40+
2. See 1.
41+
3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise.
3442
3543
## Exception safety
3644
@@ -39,7 +47,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
3947
## Exceptions
4048
4149
1. The function does not throw exceptions.
42-
2. The function can throw the following exceptions:
50+
2. The function does not throw exceptions.
51+
3. The function can throw the following exceptions:
4352
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index begins with
4453
`0`.
4554
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index was not a
@@ -74,7 +83,7 @@ Logarithmic in the size of the JSON object.
7483
--8<-- "examples/contains.output"
7584
```
7685
77-
??? example "Example (1) check with JSON pointer"
86+
??? example "Example (3) check with JSON pointer"
7887
7988
The example shows how `contains()` is used.
8089
@@ -90,5 +99,6 @@ Logarithmic in the size of the JSON object.
9099
91100
## Version history
92101
93-
1. Added in version 3.6.0.
94-
2. Added in version 3.7.0.
102+
1. Added in version 3.11.0.
103+
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0.
104+
3. Added in version 3.7.0.

doc/mkdocs/docs/api/basic_json/count.md

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
# <small>nlohmann::basic_json::</small>count
22

33
```cpp
4-
template<typename KeyT>
5-
size_type count(KeyT&& key) const;
4+
// (1)
5+
size_type count(const typename object_t::key_type& key) const;
6+
7+
// (2)
8+
template<typename KeyType>
9+
size_type count(KeyType&& key) const;
610
```
711
8-
Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will
9-
always be `0` (`key` was not found) or `1` (`key` was found).
12+
1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will
13+
always be `0` (`key` was not found) or `1` (`key` was found).
14+
2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
15+
`#!cpp typename object_comparator_t::is_transparent` denotes a type.
1016
1117
## Template parameters
1218
13-
`KeyT`
14-
: A type for an object key.
19+
`KeyType`
20+
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
21+
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
22+
This can also be a string view (C++17).
1523
1624
## Parameters
1725
@@ -52,4 +60,5 @@ This method always returns `0` when executed on a JSON type that is not an objec
5260
5361
## Version history
5462
55-
- Added in version 1.0.0.
63+
1. Added in version 3.11.0.
64+
2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# <small>nlohmann::basic_json::</small>default_object_comparator_t
2+
3+
```cpp
4+
using default_object_comparator_t = std::less<StringType>; // until C++14
5+
6+
using default_object_comparator_t = std::less<>; // since C++14
7+
```
8+
9+
The default comparator used by [`object_t`](object_t.md).
10+
11+
Since C++14 a transparent comparator is used which prevents unnecessary string construction
12+
when looking up a key in an object.
13+
14+
The actual comparator used depends on [`object_t`](object_t.md) and can be obtained via
15+
[`object_comparator_t`](object_comparator_t.md).
16+
17+
## Version history
18+
19+
- Added in version 3.11.0.

doc/mkdocs/docs/api/basic_json/erase.md

+30-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const_iterator erase(const_iterator first, const_iterator last);
1313
size_type erase(const typename object_t::key_type& key);
1414

1515
// (4)
16+
template<typename KeyType>
17+
size_type erase(KeyType&& key);
18+
19+
// (5)
1620
void erase(const size_type idx);
1721
```
1822
@@ -29,7 +33,17 @@ void erase(const size_type idx);
2933
3034
3. Removes an element from a JSON object by key.
3135
32-
4. Removes an element from a JSON array by index.
36+
4. See 3. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
37+
`#!cpp typename object_comparator_t::is_transparent` denotes a type.
38+
39+
5. Removes an element from a JSON array by index.
40+
41+
## Template parameters
42+
43+
`KeyType`
44+
: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with
45+
[`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md).
46+
This can also be a string view (C++17).
3347
3448
## Parameters
3549
@@ -56,7 +70,8 @@ void erase(const size_type idx);
5670
is returned.
5771
3. Number of elements removed. If `ObjectType` is the default `std::map` type, the return value will always be `0`
5872
(`key` was not found) or `1` (`key` was found).
59-
4. /
73+
4. See 3.
74+
5. (none)
6075
6176
## Exception safety
6277
@@ -83,7 +98,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
8398
3. The function can throw the following exceptions:
8499
- Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than
85100
JSON object; example: `"cannot use erase() with null"`
86-
4. The function can throw the following exceptions:
101+
4. See 3.
102+
5. The function can throw the following exceptions:
87103
- Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than
88104
JSON object; example: `"cannot use erase() with null"`
89105
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) when `idx >= size()`; example:
@@ -103,14 +119,16 @@ Strong exception safety: if an exception occurs, the original value stays intact
103119
- strings and binary: linear in the length of the member
104120
- other types: constant
105121
3. `log(size()) + count(key)`
106-
4. Linear in distance between `idx` and the end of the container.
122+
4. `log(size()) + count(key)`
123+
5. Linear in distance between `idx` and the end of the container.
107124
108125
## Notes
109126
110127
1. Invalidates iterators and references at or after the point of the `erase`, including the `end()` iterator.
111-
2. /
128+
2. (none)
112129
3. References and iterators to the erased elements are invalidated. Other references and iterators are not affected.
113-
4. /
130+
4. See 3.
131+
5. (none)
114132
115133
## Examples
116134
@@ -156,7 +174,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
156174
--8<-- "examples/erase__key_type.output"
157175
```
158176
159-
??? example "Example: (4) remove element from a JSON array given an index"
177+
??? example "Example: (5) remove element from a JSON array given an index"
160178
161179
The example shows the effect of `erase()` using an array index.
162180
@@ -172,5 +190,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
172190
173191
## Version history
174192
175-
- Added in version 1.0.0.
176-
- Added support for binary types in version 3.8.0.
193+
1. Added in version 1.0.0. Added support for binary types in version 3.8.0.
194+
2. Added in version 1.0.0. Added support for binary types in version 3.8.0.
195+
3. Added in version 1.0.0.
196+
4. Added in version 3.11.0.
197+
5. Added in version 1.0.0.

0 commit comments

Comments
 (0)