The requirements that basic_json places on its eleven template parameters were only implied by how the library uses the resulting object_t, array_t, string_t, etc. Consumers had to discover them by trial and error. Add "Template Parameter Requirements" collecting them, split into what is always required and what is only required when a particular part of the API is instantiated. Notable findings that were previously undocumented: - ObjectType must provide a key_compare member type (actual_object_comparator names object_t::key_compare in both arms of a std::conditional), and its third template parameter is used as a comparator, so std::unordered_map cannot be used without a wrapper. - ArrayType must provide capacity() -- push_back(), emplace_back(), operator+=(), and operator[](size_type) call it unconditionally -- and needs random-access iterators, so std::deque and std::list do not work. - StringType needs contiguous, null-terminated data(), a one-byte value_type, and either assignability from std::to_string or an ADL int_to_string(). - NumberFloatType must be float, double, or long double for parsing and serialization; the integer types must satisfy std::is_integral. - AllocatorType must be stateless, support incomplete types, and use plain pointers. - BooleanType and the number types are union members and must be trivial. Link the new page from the basic_json overview, the types feature page, and the individual type alias pages, and correct the container examples given for ObjectType (std::unordered_map) and ArrayType (std::list), which do not work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018hxZxz8svM54c6ATEvXp5E Signed-off-by: Niels Lohmann <mail@nlohmann.me>
3.6 KiB
nlohmann::basic_json::number_unsigned_t
using number_unsigned_t = NumberUnsignedType;
The type used to store JSON numbers (unsigned).
RFC 8259 describes numbers as follows:
The representation of numbers is similar to that used in most programming languages. A number is represented in base 10 using decimal digits. It contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part. Leading zeros are not allowed. (...) Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.
This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is
known whether the number is a signed integer, an unsigned integer, or a floating-point number. Therefore, three different
types, number_integer_t, number_unsigned_t and number_float_t are
used.
To store unsigned integer numbers in C++, a type is defined by the template parameter NumberUnsignedType which chooses
the type to use.
Template parameters
NumberUnsignedType- the type to store unsigned integers. It must be an unsigned integral type (
#!cpp std::is_integral) with a#!cpp std::numeric_limitsspecialization, and it must be able to represent the absolute value of everynumber_integer_tvalue. See Template Parameter Requirements.
Notes
Default type
With the default values for NumberUnsignedType (std::uint64_t), the default value for number_unsigned_t is
#!cpp std::uint64_t.
Default behavior
- The restrictions about leading zeros are not enforced in C++. Instead, leading zeros in integer literals lead to an
interpretation as an octal number. Internally, the value will be stored as a decimal number. For instance, the C++
integer literal
010will be serialized to8. During deserialization, leading zeros yield an error.
Limits
RFC 8259 specifies:
An implementation may set limits on the range and precision of numbers.
When the default type is used, the maximal integer number that can be stored is 18446744073709551615 (UINT64_MAX) and
the minimal integer number that can be stored is 0. Integer numbers that are out of range will yield over/underflow
when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored
as number_integer_t or number_float_t.
RFC 8259 further states:
Note that when such software is used, numbers that are integers and are in the range
[-2^{53}+1, 2^{53}-1]are interoperable in the sense that implementations will agree exactly on their numeric values.
As this range is a subrange (when considered in conjunction with the number_integer_t type) of the exactly supported
range [0, UINT64_MAX], this class's integer type is interoperable.
Storage
Integer number values are stored directly inside a basic_json type.
Examples
??? example
The following code shows that `number_unsigned_t` is by default, a typedef to `#!cpp std::uint64_t`.
```cpp
--8<-- "examples/number_unsigned_t.cpp"
```
Output:
```json
--8<-- "examples/number_unsigned_t.output"
```
Version history
- Added in version 2.0.0.