mirror of
https://github.com/nlohmann/json.git
synced 2026-09-29 11:10:30 +00:00
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:
@@ -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_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_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_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
|
||||
|
||||
@@ -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_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
|
||||
|
||||
??? 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_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
|
||||
|
||||
## 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
|
||||
[`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
|
||||
|
||||
@@ -59,6 +60,7 @@ Linear.
|
||||
## See also
|
||||
|
||||
- [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
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ using namespace nlohmann::literals::json_literals;
|
||||
using namespace nlohmann;
|
||||
```
|
||||
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
|
||||
|
||||
@@ -58,6 +59,7 @@ Linear.
|
||||
## See also
|
||||
|
||||
- [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
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
## `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`
|
||||
|
||||
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_NO_IO': api/macros/json_no_io.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_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
|
||||
|
||||
@@ -6423,6 +6423,7 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
||||
return j.dump();
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_UDLS
|
||||
inline namespace 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 literals
|
||||
#endif // JSON_NO_UDLS
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
///////////////////////
|
||||
@@ -6606,7 +6608,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
||||
|
||||
} // 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)
|
||||
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)
|
||||
|
||||
@@ -32504,6 +32504,7 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
||||
return j.dump();
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_UDLS
|
||||
inline namespace 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 literals
|
||||
#endif // JSON_NO_UDLS
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
///////////////////////
|
||||
@@ -32687,7 +32689,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
||||
|
||||
} // 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)
|
||||
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)
|
||||
|
||||
@@ -32,6 +32,7 @@ using NLOHMANN_JSON_NAMESPACE::ordered_json;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_map;
|
||||
using NLOHMANN_JSON_NAMESPACE::to_string;
|
||||
|
||||
#ifndef JSON_NO_UDLS
|
||||
inline namespace literals
|
||||
{
|
||||
inline namespace json_literals
|
||||
@@ -40,6 +41,7 @@ inline namespace json_literals
|
||||
using NLOHMANN_JSON_NAMESPACE::literals::json_literals::operator""_json_pointer;
|
||||
} // namespace json_literals
|
||||
} // namespace literals
|
||||
#endif
|
||||
|
||||
// Note: the following nlohmann::detail symbols must be exported due to
|
||||
// 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