From 92559b621870c90f59e8a5032147c953b25be100 Mon Sep 17 00:00:00 2001 From: Florian Albrechtskirchinger Date: Sat, 6 Aug 2022 16:24:22 +0200 Subject: [PATCH] Update documentation --- docs/docset/docSet.sql | 2 + docs/examples/nlohmann_json_namespace.output | 2 +- .../nlohmann_json_namespace_no_version.cpp | 13 +++ .../nlohmann_json_namespace_no_version.output | 1 + docs/mkdocs/docs/api/macros/index.md | 5 +- .../api/macros/nlohmann_json_namespace.md | 16 ++-- .../macros/nlohmann_json_namespace_begin.md | 43 +++++---- .../nlohmann_json_namespace_no_version.md | 45 +++++++++ docs/mkdocs/docs/features/namespace.md | 93 +++++++++++++++++++ docs/mkdocs/mkdocs.yml | 2 + 10 files changed, 194 insertions(+), 28 deletions(-) create mode 100644 docs/examples/nlohmann_json_namespace_no_version.cpp create mode 100644 docs/examples/nlohmann_json_namespace_no_version.output create mode 100644 docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md create mode 100644 docs/mkdocs/docs/features/namespace.md diff --git a/docs/docset/docSet.sql b/docs/docset/docSet.sql index e076ea575..b21184637 100644 --- a/docs/docset/docSet.sql +++ b/docs/docset/docSet.sql @@ -181,6 +181,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('Iterators', 'Guide', 'feature INSERT INTO searchIndex(name, type, path) VALUES ('JSON Merge Patch', 'Guide', 'features/merge_patch/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON Patch and Diff', 'Guide', 'features/json_patch/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON Pointer', 'Guide', 'features/json_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('nlohmann Namespace', 'Guide', 'features/namespace/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('Types', 'Guide', 'features/types/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('Types: Number Handling', 'Guide', 'features/types/number_handling/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('Object Order', 'Guide', 'features/object_order/index.html'); @@ -223,6 +224,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTR INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE', 'Macro', 'api/macros/nlohmann_json_namespace/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_BEGIN', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_END', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_NO_VERSION', 'Macro', 'api/macros/nlohmann_json_namespace_no_version/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM', 'Macro', 'api/macros/nlohmann_json_serialize_enum/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MAJOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MINOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html'); diff --git a/docs/examples/nlohmann_json_namespace.output b/docs/examples/nlohmann_json_namespace.output index d5a8b59d6..e943d3444 100644 --- a/docs/examples/nlohmann_json_namespace.output +++ b/docs/examples/nlohmann_json_namespace.output @@ -1 +1 @@ -nlohmann::json_v3_11_1 +nlohmann::json_abi_v3_11_1 diff --git a/docs/examples/nlohmann_json_namespace_no_version.cpp b/docs/examples/nlohmann_json_namespace_no_version.cpp new file mode 100644 index 000000000..97948dd7e --- /dev/null +++ b/docs/examples/nlohmann_json_namespace_no_version.cpp @@ -0,0 +1,13 @@ +#include + +#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 1 +#include + +// macro needed to output the NLOHMANN_JSON_NAMESPACE as string literal +#define Q(x) #x +#define QUOTE(x) Q(x) + +int main() +{ + std::cout << QUOTE(NLOHMANN_JSON_NAMESPACE) << std::endl; +} diff --git a/docs/examples/nlohmann_json_namespace_no_version.output b/docs/examples/nlohmann_json_namespace_no_version.output new file mode 100644 index 000000000..1c8f3132b --- /dev/null +++ b/docs/examples/nlohmann_json_namespace_no_version.output @@ -0,0 +1 @@ +nlohmann::json_abi diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md index 8e118b03f..099dfa671 100644 --- a/docs/mkdocs/docs/api/macros/index.md +++ b/docs/mkdocs/docs/api/macros/index.md @@ -32,7 +32,10 @@ header. See also the [macro overview page](../../features/macros.md). ## Library namespace - [**NLOHMANN_JSON_NAMESPACE**](nlohmann_json_namespace.md) - full name of the `nlohmann` namespace -- [**NLOHMANN_JSON_NAMESPACE_BEGIN**
**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and close the library namespace +- [**NLOHMANN_JSON_NAMESPACE_BEGIN**
**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and + close the library namespace +- [**NLOHMANN_JSON_NAMESPACE_NO_VERSION**](nlohmann_json_namespace_no_version.md) - disable the version component of + the inline namespace ## Type conversions diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md index b44538e18..5c54dba52 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md @@ -1,19 +1,18 @@ # NLOHMANN_JSON_NAMESPACE ```cpp -#define NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE /* value */ ``` -This macro evaluates to the full name of the `nlohmann` namespace, including the name of a versioned and ABI-tagged -inline namespace. Use this macro to unambiguously refer to the `nlohmann` namespace. +This macro evaluates to the full name of the `nlohmann` namespace. ## Default definition -The default value consists of a prefix, a version string, and optional ABI tags depending on whether ABI-affecting -macros are defined (e.g., [`JSON_DIAGNOSTICS`](json_diagnostics.md), and -[`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](json_use_legacy_discarded_value_comparison.md)). +The default value consists of the root namespace (`nlohmann`) and an inline ABI namespace. See +[`nlohmann` Namespace](../../features/namespace.md#structure) for details. -When the macro is not defined, the library will define it to its default value. +When the macro is not defined, the library will define it to its default value. Overriding this value has no effect on +the library. ## Examples @@ -35,7 +34,8 @@ When the macro is not defined, the library will define it to its default value. ## See also - [`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](nlohmann_json_namespace_begin.md) +- [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](nlohmann_json_namespace_no_version.md) ## Version history -- Added in version 3.11.0. +- Added in version 3.11.0. Changed inline namespace name in version 3.11.2. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md index 5fd8fba2d..1374264a3 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md @@ -1,30 +1,35 @@ # NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END ```cpp -#define NLOHMANN_JSON_NAMESPACE_BEGIN // (1) -#define NLOHMANN_JSON_NAMESPACE_END // (2) +#define NLOHMANN_JSON_NAMESPACE_BEGIN /* value */ // (1) +#define NLOHMANN_JSON_NAMESPACE_END /* value */ // (2) ``` -These macros can be used to open and close the `nlohmann` namespace. They include an inline namespace used to -differentiate symbols when linking multiple versions (including different ABI-affecting macros) of this library. +These macros can be used to open and close the `nlohmann` namespace. See +[`nlohmann` Namespace](../../features/namespace.md#structure) for details. 1. Opens the namespace. - ```cpp - namespace nlohmann - { - inline namespace json_v3_11_0 - { - ``` - 2. Closes the namespace. - ```cpp - } // namespace nlohmann - } // json_v3_11_0 - ``` ## Default definition -The default definitions open and close the `nlohmann` as well as an inline namespace. +The default definitions open and close the `nlohmann` namespace. The precise definition of +[`NLOHMANN_JSON_NAMESPACE_BEGIN`] varies as described [here](../../features/namespace.md#structure). + +1. Default definition of `NLOHMANN_JSON_NAMESPACE_BEGIN`: + + ```cpp + namespace nlohmann + { + inline namespace json_abi_v3_11_2 + { + ``` + +2. Default definition of `NLOHMANN_JSON_NAMESPACE_END`: + ```cpp + } // namespace json_abi_v3_11_2 + } // namespace nlohmann + ``` When these macros are not defined, the library will define them to their default definitions. @@ -32,7 +37,7 @@ When these macros are not defined, the library will define them to their default ??? example - The example shows an example how to use `NLOHMANN_JSON_NAMESPACE_BEGIN`/`NLOHMANN_JSON_NAMESPACE_END` from the + The example shows how to use `NLOHMANN_JSON_NAMESPACE_BEGIN`/`NLOHMANN_JSON_NAMESPACE_END` from the [How do I convert third-party types?](../../features/arbitrary_types.md#how-do-i-convert-third-party-types) page. ```cpp @@ -47,8 +52,10 @@ When these macros are not defined, the library will define them to their default ## See also +- [`nlohmann` Namespace](../../features/namespace.md) - [NLOHMANN_JSON_NAMESPACE](nlohmann_json_namespace.md) +- [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](nlohmann_json_namespace_no_version.md) ## Version history -- Added in version 3.11.0. +- Added in version 3.11.0. Changed inline namespace name in version 3.11.2. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md new file mode 100644 index 000000000..9e2a52d04 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md @@ -0,0 +1,45 @@ +# NLOHMANN_JSON_NAMESPACE_NO_VERSION + +```cpp +#define NLOHMANN_JSON_NAMESPACE_NO_VERSION /* value */ +``` + +If defined to `1`, the version component is omitted from the inline namespace. See +[`nlohmann` Namespace](../../features/namespace.md#structure) for details. + +## Default definition + +The default value is `0`. + +```cpp +#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Examples + +??? example + + The example shows how to use `NLOHMANN_JSON_NAMESPACE_NO_VERSION` to disable the version component of the inline + namespace. + + ```cpp + --8<-- "examples/nlohmann_json_namespace_no_version.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_namespace_no_version.output" + ``` + +## See also + +- [`nlohmann` Namespace](../../features/namespace.md) +- [`NLOHMANN_JSON_NAMESPACE`](nlohmann_json_namespace.md) +- [`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](nlohmann_json_namespace_begin.md) + +## Version history + +- Added in version 3.11.2. diff --git a/docs/mkdocs/docs/features/namespace.md b/docs/mkdocs/docs/features/namespace.md new file mode 100644 index 000000000..8cee2ccfe --- /dev/null +++ b/docs/mkdocs/docs/features/namespace.md @@ -0,0 +1,93 @@ +# `nlohmann` Namespace + +The 3.11.0 release introduced an +[inline namespace](https://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces) to allow different parts of +a codebase to safely use different versions of the JSON library as long as they never exchange instances of library +types. + +## Structure + +The complete default namespace name is derived as follows: + +- The root namespace is always `nlohmann`. +- The inline namespace starts with `json_abi` and is followed by serveral optional ABI tags according to the value of + these ABI-affecting macros, in order: + - [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) defined non-zero appends `_diag`. + - [`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](../api/macros/json_use_legacy_discarded_value_comparison.md) + defined non-zero appends `_ldvcmp`. +- The inline namespace ends with the suffix `_v` followed by the 3 components of the version number separated by + underscores. To omit the version component, see [Disabling the version component](#disabling-the-version-component) + below. + +For example, the namespace name for version 3.11.2 with `JSON_DIAGNOSTICS` defined to `1` is: + +```cpp +nlohmann::json_abi_diag_v3_11_2 +``` + +## Purpose + +Several incompatibilities have been observed. Amongst the most common ones is linking code compiled with different +definitions of [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This is illustrated in the diagram below. + +```plantuml +[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=0] as [json] +[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=1] as [json_diag] +[**some_library**] as [library] +[**application**] as [app] + +[library] ..|> [json] +[app] ..|> [json_diag] +[app] ..|>[library] +``` + +In releases prior to 3.11.0, mixing any version of the JSON library with different `JSON_DIAGNOSTICS` settings would +result in a crashing application. If `some_library` never passes instances of JSON library types to the application, +this scenario became safe in version 3.11.0 and above due to the inline namespace yielding distinct symbol names. + +## Limitations + +Neither the compiler nor the linker will issue as much as a warning when translation units – intended to be linked +together and that include different versions and/or configurations of the JSON library – exchange and use library +types. + +There is an exception when forward declarations are used (i.e., when including `json_fwd.hpp`) in which case the linker +may complain about undefined references. + +## Disabling the version component + +Different versions are not necessarily ABI-incompatible, but the project does not actively track changes in the ABI and +recommends that all parts of a codebase exchanging library types be built with the same version. Users can, **at their +own risk**, disable the version component of the linline namespace, allowing different versions – but not +configurations – to be used in cases where the linker would otherwise output undefined reference errors. + +To do so, define [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](../api/macros/nlohmann_json_namespace_no_version.md) to `1`. + +This applies to version 3.11.2 and above only, versions 3.11.0 and 3.11.1 can apply the technique described in the next +section to emulate the effect of the `NLOHMANN_JSON_NAMESPACE_NO_VERSION` macro. + +!!! danger "Use at your own risk" + + Disabling the namespace version component and mixing ABI-incompatible versions will result in crashes or incorrect + behavior. You have been warned! +## Disabling the inline namespace completely + +When interoperability with code using a pre-3.11.0 version of the library is required, users can, **at their own risk** +restore the old namespace layout by redefining +[`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](../api/macros/nlohmann_json_namespace_begin.md) as +follows: + +```cpp +#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann { +#define NLOHMANN_JSON_NAMESPACE_END } +``` + +!!! danger "Use at your own risk" + + Overriding the namespace and mixing ABI-incompatible versions will result in crashes or incorrect behavior. You + have been warned! + +## Version history + +- Introduced inline namespace (`json_v3_11_0[_abi-tag]*`) in version 3.11.0. +- Changed structure of inline namespace in version 3.11.2. diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index f88784f3e..545584a92 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -58,6 +58,7 @@ nav: - features/json_pointer.md - features/json_patch.md - features/merge_patch.md + - 'nlohmann Namespace': features/namespace.md - features/object_order.md - Parsing: - features/parsing/index.md @@ -270,6 +271,7 @@ nav: - 'NLOHMANN_JSON_NAMESPACE': api/macros/nlohmann_json_namespace.md - 'NLOHMANN_JSON_NAMESPACE_BEGIN': api/macros/nlohmann_json_namespace_begin.md - 'NLOHMANN_JSON_NAMESPACE_END': api/macros/nlohmann_json_namespace_begin.md + - 'NLOHMANN_JSON_NAMESPACE_NO_VERSION': api/macros/nlohmann_json_namespace_no_version.md - 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md - 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md