Skip to content

Commit

Permalink
Add note on derived return type for value function (#4628)
Browse files Browse the repository at this point in the history
* 📝 add note on derived return type

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📝 add note on derived return type

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
  • Loading branch information
nlohmann authored Jan 26, 2025
1 parent d0789e3 commit e90c860
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 11 deletions.
4 changes: 2 additions & 2 deletions docs/mkdocs/docs/api/basic_json/at.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
## See also
- documentation on [checked access](../../features/element_access/checked_access.md)
- see [`operator[]`](operator%5B%5D.md) for unchecked access by reference
- see [`value`](value.md) for access with default value
- [`operator[]`](operator%5B%5D.md) for unchecked access by reference
- [`value`](value.md) for access with default value
## Version history
Expand Down
24 changes: 24 additions & 0 deletions docs/mkdocs/docs/api/basic_json/value.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,30 @@ changes to any JSON value.
2. Logarithmic in the size of the container.
3. Logarithmic in the size of the container.
## Notes
!!! warning "Return type"
The value function is a template, and the return type of the function is determined by the type of the provided
default value unless otherwise specified. This can have unexpected effects. In the example below, we store a 64-bit
unsigned integer. We get exactly that value when using [`operator[]`](operator[].md). However, when we call `value`
and provide `#!c 0` as default value, then `#!c -1` is returned. The occurs, because `#!c 0` has type `#!c int`
which overflows when handling the value `#!c 18446744073709551615`.
To address this issue, either provide a correctly typed default value or use the template parameter to specify the
desired return type. Note that this issue occurs even when a value is stored at the provided key, and the default
value is not used as the return value.
```cpp
--8<-- "examples/value__return_type.cpp"
```
Output:
```json
--8<-- "examples/value__return_type.output"
```
## Examples
??? example "Example: (1) access specified object element with default value"
Expand Down
14 changes: 14 additions & 0 deletions docs/mkdocs/docs/examples/value__return_type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
json j = json::parse(R"({"uint64": 18446744073709551615})");

std::cout << "operator[]: " << j["uint64"] << '\n'
<< "default value (int): " << j.value("uint64", 0) << '\n'
<< "default value (uint64_t): " << j.value("uint64", std::uint64_t(0)) << '\n'
<< "explict return value type: " << j.value<std::uint64_t>("uint64", 0) << '\n';
}
4 changes: 4 additions & 0 deletions docs/mkdocs/docs/examples/value__return_type.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
operator[]: 18446744073709551615
default value (int): -1
default value (uint64_t): 18446744073709551615
explict return value type: 18446744073709551615
49 changes: 40 additions & 9 deletions docs/mkdocs/docs/features/element_access/default_value.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

## Overview

In many situations such as configuration files, missing values are not exceptional, but may be treated as if a default value was present.
In many situations such as configuration files, missing values are not exceptional, but may be treated as if a default
value was present. For this case, use [`value(key, default_value)`](../../api/basic_json/value.md) which takes the key
you want to access and a default value in case there is no value stored with that key.

## Example

??? example

Expand All @@ -17,16 +21,43 @@ In many situations such as configuration files, missing values are not exception

Assume the value is parsed to a `json` variable `j`.

| expression | value |
| ---------- | ----- |
| `#!cpp j` | `#!json {"logOutput": "result.log", "append": true}` |
| `#!cpp j.value("logOutput", "logfile.log")` | `#!json "result.log"` |
| `#!cpp j.value("append", true)` | `#!json true` |
| `#!cpp j.value("append", false)` | `#!json true` |
| `#!cpp j.value("logLevel", "verbose")` | `#!json "verbose"` |
| expression | value |
|---------------------------------------------|------------------------------------------------------|
| `#!cpp j` | `#!json {"logOutput": "result.log", "append": true}` |
| `#!cpp j.value("logOutput", "logfile.log")` | `#!json "result.log"` |
| `#!cpp j.value("append", true)` | `#!json true` |
| `#!cpp j.value("append", false)` | `#!json true` |
| `#!cpp j.value("logLevel", "verbose")` | `#!json "verbose"` |

## Note
## Notes

!!! failure "Exceptions"

- `value` can only be used with objects. For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.

!!! warning "Return type"

The value function is a template, and the return type of the function is determined by the type of the provided
default value unless otherwise specified. This can have unexpected effects. In the example below, we store a 64-bit
unsigned integer. We get exactly that value when using [`operator[]`](../../api/basic_json/operator[].md). However,
when we call `value` and provide `#!c 0` as default value, then `#!c -1` is returned. The occurs, because `#!c 0`
has type `#!c int` which overflows when handling the value `#!c 18446744073709551615`.

To address this issue, either provide a correctly typed default value or use the template parameter to specify the
desired return type. Note that this issue occurs even when a value is stored at the provided key, and the default
value is not used as the return value.

```cpp
--8<-- "examples/value__return_type.cpp"
```

Output:

```json
--8<-- "examples/value__return_type.output"
```

## See also

- [`value`](../../api/basic_json/value.md) for access with default value
- documentation on [checked access](checked_access.md)

0 comments on commit e90c860

Please sign in to comment.