Add JSON_NO_UDLS to leave out the user-defined string literals
The bodies of operator""_json and operator""_json_pointer call the parser, so every translation unit including the library instantiates it, even if it never parses anything. Defining JSON_NO_UDLS leaves the literals out entirely, which saves 15-35% compile time for such translation units (#5294). Nothing changes if the macro is not defined. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
11 files changed
+167
-4
No files matched your search
@@ -30,6 +30,7 @@ header. See also the [macro overview page](../../features/macros.md).
|
|||||||
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
||||||
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||||
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||||
|
- [**JSON_NO_UDLS**](json_no_udls.md) - leave out the user-defined string literals (UDLs) to reduce compile time
|
||||||
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
||||||
- [**JSON_USE_GLOBAL_UDLS**](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
- [**JSON_USE_GLOBAL_UDLS**](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||||
- [**JSON_USE_SIMDUTF**](json_use_simdutf.md) - use the simdutf library to accelerate UTF-8 validation
|
- [**JSON_USE_SIMDUTF**](json_use_simdutf.md) - use the simdutf library to accelerate UTF-8 validation
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# JSON_NO_UDLS
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_NO_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
When defined, the user-defined string literals [`operator""_json`](../operator_literal_json.md) and
|
||||||
|
[`operator""_json_pointer`](../operator_literal_json_pointer.md) are not defined, neither in the namespace
|
||||||
|
`nlohmann::literals::json_literals` nor in the global namespace (regardless of
|
||||||
|
[`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md)).
|
||||||
|
|
||||||
|
The literals are ordinary inline functions whose bodies call the parser, so every translation unit that includes the
|
||||||
|
library instantiates the parser — even if it never parses anything itself. Defining `JSON_NO_UDLS` avoids this and
|
||||||
|
reduces the compile time of such translation units (e.g., ones that only define types and conversions or pass `json`
|
||||||
|
values around). Everything else in the library is unaffected; use [`parse`](../basic_json/parse.md) and the
|
||||||
|
[`json_pointer`](../json_pointer/json_pointer.md) constructor instead of the literals.
|
||||||
|
|
||||||
|
## Default definition
|
||||||
|
|
||||||
|
By default, `#!cpp JSON_NO_UDLS` is not defined.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#undef JSON_NO_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
!!! info "Per translation unit"
|
||||||
|
|
||||||
|
The macro only removes declarations, so it can be defined for some translation units and not for others. Code that
|
||||||
|
uses `_json` or `_json_pointer` fails to compile when `JSON_NO_UDLS` is defined.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The code below leaves out the user-defined string literals and uses `parse` and the `json_pointer` constructor
|
||||||
|
instead.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_NO_UDLS 1
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// auto j = R"({"foo": 42})"_json; // This line would fail to compile
|
||||||
|
auto j = nlohmann::json::parse(R"({"foo": 42})");
|
||||||
|
auto p = nlohmann::json::json_pointer("/foo");
|
||||||
|
return j.at(p) == 42 ? 0 : 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
- Added in version 3.13.0.
|
||||||
@@ -32,6 +32,10 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
||||||
`JSON_USE_GLOBAL_UDLS` accordingly.
|
`JSON_USE_GLOBAL_UDLS` accordingly.
|
||||||
|
|
||||||
|
!!! info "Leaving out the literals"
|
||||||
|
|
||||||
|
If [`JSON_NO_UDLS`](json_no_udls.md) is defined, the literals are not defined at all and this macro has no effect.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example "Example 1: Default behavior"
|
??? example "Example 1: Default behavior"
|
||||||
@@ -92,6 +96,7 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
- [`operator""_json`](../operator_literal_json.md)
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_NO_UDLS`](json_no_udls.md) - leave out the user-defined string literals entirely
|
||||||
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ using namespace nlohmann;
|
|||||||
```
|
```
|
||||||
|
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is not defined if
|
||||||
|
[`JSON_NO_UDLS`](macros/json_no_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
||||||
|
- [JSON_NO_UDLS](macros/json_no_udls.md) - leave out the user-defined string literals
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ using namespace nlohmann::literals::json_literals;
|
|||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
```
|
```
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is not defined if
|
||||||
|
[`JSON_NO_UDLS`](macros/json_no_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
||||||
|
- [JSON_NO_UDLS](macros/json_no_udls.md) - leave out the user-defined string literals
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,14 @@ same values and the same comparisons.
|
|||||||
|
|
||||||
See [full documentation of `JSON_NO_THREAD_LOCAL`](../api/macros/json_no_thread_local.md).
|
See [full documentation of `JSON_NO_THREAD_LOCAL`](../api/macros/json_no_thread_local.md).
|
||||||
|
|
||||||
|
## `JSON_NO_UDLS`
|
||||||
|
|
||||||
|
When defined, the user-defined string literals `operator""_json` and `operator""_json_pointer` are left out entirely. This
|
||||||
|
reduces the compile time of translation units that do not use them, because the literals would otherwise instantiate
|
||||||
|
the parser in every translation unit that includes the library.
|
||||||
|
|
||||||
|
See [full documentation of `JSON_NO_UDLS`](../api/macros/json_no_udls.md).
|
||||||
|
|
||||||
## `JSON_PRECISE_STREAM_POSITION`
|
## `JSON_PRECISE_STREAM_POSITION`
|
||||||
|
|
||||||
When defined to `1`, [`operator>>`](../api/operator_gtgt.md) and non-strict
|
When defined to `1`, [`operator>>`](../api/operator_gtgt.md) and non-strict
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ nav:
|
|||||||
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
||||||
- 'JSON_NO_IO': api/macros/json_no_io.md
|
- 'JSON_NO_IO': api/macros/json_no_io.md
|
||||||
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
||||||
|
- 'JSON_NO_UDLS': api/macros/json_no_udls.md
|
||||||
- 'JSON_PRECISE_STREAM_POSITION': api/macros/json_precise_stream_position.md
|
- 'JSON_PRECISE_STREAM_POSITION': api/macros/json_precise_stream_position.md
|
||||||
- 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md
|
- 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md
|
||||||
- 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md
|
- 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md
|
||||||
|
|||||||
@@ -6423,6 +6423,7 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
|||||||
return j.dump();
|
return j.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef JSON_NO_UDLS
|
||||||
inline namespace literals
|
inline namespace literals
|
||||||
{
|
{
|
||||||
inline namespace json_literals
|
inline namespace json_literals
|
||||||
@@ -6472,6 +6473,7 @@ inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, st
|
|||||||
|
|
||||||
} // namespace json_literals
|
} // namespace json_literals
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
#endif // JSON_NO_UDLS
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -6606,7 +6608,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#if JSON_USE_GLOBAL_UDLS
|
#if JSON_USE_GLOBAL_UDLS && !defined(JSON_NO_UDLS)
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
||||||
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
|||||||
@@ -32504,6 +32504,7 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
|||||||
return j.dump();
|
return j.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef JSON_NO_UDLS
|
||||||
inline namespace literals
|
inline namespace literals
|
||||||
{
|
{
|
||||||
inline namespace json_literals
|
inline namespace json_literals
|
||||||
@@ -32553,6 +32554,7 @@ inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, st
|
|||||||
|
|
||||||
} // namespace json_literals
|
} // namespace json_literals
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
#endif // JSON_NO_UDLS
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -32687,7 +32689,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#if JSON_USE_GLOBAL_UDLS
|
#if JSON_USE_GLOBAL_UDLS && !defined(JSON_NO_UDLS)
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
||||||
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ using NLOHMANN_JSON_NAMESPACE::ordered_json;
|
|||||||
using NLOHMANN_JSON_NAMESPACE::ordered_map;
|
using NLOHMANN_JSON_NAMESPACE::ordered_map;
|
||||||
using NLOHMANN_JSON_NAMESPACE::to_string;
|
using NLOHMANN_JSON_NAMESPACE::to_string;
|
||||||
|
|
||||||
|
#ifndef JSON_NO_UDLS
|
||||||
inline namespace literals
|
inline namespace literals
|
||||||
{
|
{
|
||||||
inline namespace json_literals
|
inline namespace json_literals
|
||||||
@@ -40,6 +41,7 @@ inline namespace json_literals
|
|||||||
using NLOHMANN_JSON_NAMESPACE::literals::json_literals::operator""_json_pointer;
|
using NLOHMANN_JSON_NAMESPACE::literals::json_literals::operator""_json_pointer;
|
||||||
} // namespace json_literals
|
} // namespace json_literals
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
#endif
|
||||||
|
|
||||||
// Note: the following nlohmann::detail symbols must be exported due to
|
// Note: the following nlohmann::detail symbols must be exported due to
|
||||||
// an MSVC bug failing to compile without these symbols visible (ticket #3970)
|
// an MSVC bug failing to compile without these symbols visible (ticket #3970)
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// This translation unit checks JSON_NO_UDLS, which leaves out the user-defined
|
||||||
|
// string literals operator""_json and operator""_json_pointer entirely (see
|
||||||
|
// #5294), while the rest of the library keeps working.
|
||||||
|
#define JSON_NO_UDLS 1
|
||||||
|
|
||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
// An argument type whose associated namespace is the library namespace, so
|
||||||
|
// argument-dependent lookup of a literal operator called by its function name
|
||||||
|
// also searches the inline namespaces nlohmann::literals::json_literals.
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
struct no_udls_probe
|
||||||
|
{
|
||||||
|
operator const char* () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// The calls below use a dependent argument, so a literal operator that is not
|
||||||
|
// declared at all is a substitution failure rather than a hard error: lookup is
|
||||||
|
// deferred to the point of instantiation, where it considers the declarations
|
||||||
|
// visible from here (the global using-declarations of JSON_USE_GLOBAL_UDLS) plus
|
||||||
|
// argument-dependent lookup (the literals in the library namespace).
|
||||||
|
template<typename T>
|
||||||
|
using json_udl_t = decltype(operator""_json(std::declval<T>(), std::size_t()));
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using json_pointer_udl_t = decltype(operator""_json_pointer(std::declval<T>(), std::size_t()));
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using has_json_udl = nlohmann::detail::is_detected<json_udl_t, T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using has_json_pointer_udl = nlohmann::detail::is_detected<json_pointer_udl_t, T>;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("JSON_NO_UDLS")
|
||||||
|
{
|
||||||
|
SECTION("literals are not declared")
|
||||||
|
{
|
||||||
|
// global namespace (JSON_USE_GLOBAL_UDLS defaults to 1)
|
||||||
|
CHECK_FALSE(has_json_udl<const char*>::value);
|
||||||
|
CHECK_FALSE(has_json_pointer_udl<const char*>::value);
|
||||||
|
|
||||||
|
// nlohmann::literals::json_literals
|
||||||
|
CHECK_FALSE(has_json_udl<nlohmann::no_udls_probe>::value);
|
||||||
|
CHECK_FALSE(has_json_pointer_udl<nlohmann::no_udls_probe>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("the rest of the library keeps working")
|
||||||
|
{
|
||||||
|
const json j = json::parse(R"({"foo": {"bar": 42}})");
|
||||||
|
CHECK(j.dump() == R"({"foo":{"bar":42}})");
|
||||||
|
|
||||||
|
const json::json_pointer ptr("/foo/bar");
|
||||||
|
CHECK(j.at(ptr) == 42);
|
||||||
|
CHECK(j.contains(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user