Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add versioned, ABI-tagged inline namespace and namespace macros #3590

Merged
merged 12 commits into from
Jul 30, 2022
Merged
7 changes: 5 additions & 2 deletions Makefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ SED:=$(shell command -v gsed || which sed)
# the list of sources in the include folder # the list of sources in the include folder
SRCS=$(shell find include -type f | sort) SRCS=$(shell find include -type f | sort)


# the list of sources in the tests folder
TESTS_SRCS=$(shell find tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' | sort)

# the single header (amalgamated from the source files) # the single header (amalgamated from the source files)
AMALGAMATED_FILE=single_include/nlohmann/json.hpp AMALGAMATED_FILE=single_include/nlohmann/json.hpp


Expand Down Expand Up @@ -159,11 +162,11 @@ pretty:
--preserve-date \ --preserve-date \
--suffix=none \ --suffix=none \
--formatted \ --formatted \
$(SRCS) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp tests/benchmarks/src/benchmarks.cpp docs/examples/*.cpp $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp


# call the Clang-Format on all source files # call the Clang-Format on all source files
pretty_format: pretty_format:
for FILE in $(SRCS) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp benchmarks/src/benchmarks.cpp docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done


# create single header file # create single header file
amalgamate: $(AMALGAMATED_FILE) amalgamate: $(AMALGAMATED_FILE)
Expand Down
5 changes: 5 additions & 0 deletions docs/mkdocs/docs/api/macros/index.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ header. See also the [macro overview page](../../features/macros.md).
- [**JSON_SKIP_LIBRARY_VERSION_CHECK**](json_skip_library_version_check.md) - skip library version check - [**JSON_SKIP_LIBRARY_VERSION_CHECK**](json_skip_library_version_check.md) - skip library version check
- [**NLOHMANN_JSON_VERSION_MAJOR**<br>**NLOHMANN_JSON_VERSION_MINOR**<br>**NLOHMANN_JSON_VERSION_PATCH**](nlohmann_json_version_major.md) - library version information - [**NLOHMANN_JSON_VERSION_MAJOR**<br>**NLOHMANN_JSON_VERSION_MINOR**<br>**NLOHMANN_JSON_VERSION_PATCH**](nlohmann_json_version_major.md) - library version information


## Library namespace

- [**NLOHMANN_JSON_NAMESPACE**](nlohmann_json_namespace.md) - full name of the `nlohmann` namespace
- [**NLOHMANN_JSON_NAMESPACE_BEGIN**<br>**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and close the library namespace

## Type conversions ## Type conversions


- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums - [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums
Expand Down
14 changes: 10 additions & 4 deletions docs/mkdocs/docs/api/macros/json_diagnostics.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ When the macro is not defined, the library will define it to its default value.


## Notes ## Notes


!!! danger "ABI incompatibility" !!! note "ABI compatibility"


As this macro changes the definition of the `basic_json` object, it MUST be defined in the same way globally, even As of version 3.11.0, this macro is no longer required to be defined consistently throughout a codebase to avoid
across different compilation units: `basic_json` objects with differently defined `JSON_DIAGNOSTICS` macros are One Definition Rule (ODR) violations, as the value of this macro is encoded in the namespace, resulting in distinct
not compatible! symbol names.

This allows different parts of a codebase to use different versions or configurations of this library without
causing improper behavior.

Where possible, it is still recommended that all code define this the same way for maximum interoperability.


## Examples ## Examples


Expand Down Expand Up @@ -65,3 +70,4 @@ When the macro is not defined, the library will define it to its default value.
## Version history ## Version history


- Added in version 3.10.0. - Added in version 3.10.0.
- As of version 3.11.0 the definition is allowed to vary between translation units.
26 changes: 26 additions & 0 deletions docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,26 @@
# NLOHMANN_JSON_NAMESPACE

```cpp
#define NLOHMANN_JSON_NAMESPACE
```

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.

## 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)).

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)

## Version history

- Added in version 3.11.0.
40 changes: 40 additions & 0 deletions docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,40 @@
# NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END

```cpp
#define NLOHMANN_JSON_NAMESPACE_BEGIN // (1)
#define NLOHMANN_JSON_NAMESPACE_END // (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.

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.

When these macros are not defined, the library will define them to their
default definitions.

## See also

- [NLOHMANN_JSON_NAMESPACE](nlohmann_json_namespace.md)

## Version history

- Added in version 3.11.0.
9 changes: 7 additions & 2 deletions docs/mkdocs/docs/features/arbitrary_types.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ To solve this, you need to add a specialization of `adl_serializer` to the `nloh


```cpp ```cpp
// partial specialization (full specialization works too) // partial specialization (full specialization works too)
namespace nlohmann { NLOHMANN_JSON_NAMESPACE_BEGIN
template <typename T> template <typename T>
struct adl_serializer<boost::optional<T>> { struct adl_serializer<boost::optional<T>> {
static void to_json(json& j, const boost::optional<T>& opt) { static void to_json(json& j, const boost::optional<T>& opt) {
Expand All @@ -176,9 +176,14 @@ namespace nlohmann {
} }
} }
}; };
} NLOHMANN_JSON_NAMESPACE_END
``` ```


!!! note "ABI compatibility"

Use [`NLOHMANN_JSON_NAMESPACE_BEGIN`](../api/macros/nlohmann_json_namespace_begin.md) and `NLOHMANN_JSON_NAMESPACE_END`
instead of `#!cpp namespace nlohmann { }` in code which may be linked with different versions of this library.

## How can I use `get()` for non-default constructible/non-copyable types? ## How can I use `get()` for non-default constructible/non-copyable types?


There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
Expand Down
3 changes: 3 additions & 0 deletions docs/mkdocs/mkdocs.yml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ nav:
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md
- '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_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.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_MAJOR': api/macros/nlohmann_json_version_major.md
- 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md
Expand Down
9 changes: 4 additions & 5 deletions include/nlohmann/adl_serializer.hpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@


#pragma once #pragma once


#include <type_traits>
#include <utility> #include <utility>


#include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/conversions/from_json.hpp> #include <nlohmann/detail/conversions/from_json.hpp>
#include <nlohmann/detail/conversions/to_json.hpp> #include <nlohmann/detail/conversions/to_json.hpp>
#include <nlohmann/detail/meta/identity_tag.hpp> #include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>


namespace nlohmann NLOHMANN_JSON_NAMESPACE_BEGIN
{


/// @sa https://json.nlohmann.me/api/adl_serializer/ /// @sa https://json.nlohmann.me/api/adl_serializer/
template<typename ValueType, typename> template<typename ValueType, typename>
Expand Down Expand Up @@ -53,4 +51,5 @@ struct adl_serializer
::nlohmann::to_json(j, std::forward<TargetType>(val)); ::nlohmann::to_json(j, std::forward<TargetType>(val));
} }
}; };
} // namespace nlohmann
NLOHMANN_JSON_NAMESPACE_END
7 changes: 4 additions & 3 deletions include/nlohmann/byte_container_with_subtype.hpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
#include <tuple> // tie #include <tuple> // tie
#include <utility> // move #include <utility> // move


namespace nlohmann #include <nlohmann/detail/abi_macros.hpp>
{
NLOHMANN_JSON_NAMESPACE_BEGIN


/// @brief an internal type for a backed binary type /// @brief an internal type for a backed binary type
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
Expand Down Expand Up @@ -99,4 +100,4 @@ class byte_container_with_subtype : public BinaryType
bool m_has_subtype = false; bool m_has_subtype = false;
}; };


} // namespace nlohmann NLOHMANN_JSON_NAMESPACE_END
71 changes: 71 additions & 0 deletions include/nlohmann/detail/abi_macros.hpp
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

// This file contains all macro definitions affecting or depending on the ABI

#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
nlohmann marked this conversation as resolved.
Show resolved Hide resolved
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 10 || NLOHMANN_JSON_VERSION_PATCH != 5
#warning "Already included a different version of the library!"
#endif
#endif
#endif

#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_MINOR 10 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 5 // NOLINT(modernize-macro-to-enum)

#ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#endif

#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif

#if JSON_DIAGNOSTICS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif

#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
#endif

#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \
json_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \
NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch)

#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c
#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \
NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c)

#define NLOHMANN_JSON_ABI_STRING \
NLOHMANN_JSON_ABI_CONCAT( \
NLOHMANN_JSON_ABI_PREFIX( \
NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH), \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)

#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING
#endif

#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_ABI_STRING \
{
#endif

#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (abi_string) */ \
} /* namespace nlohmann */
#endif
23 changes: 6 additions & 17 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,28 +24,15 @@
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/identity_tag.hpp> #include <nlohmann/detail/meta/identity_tag.hpp>
#include <nlohmann/detail/meta/std_fs.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>


#if JSON_HAS_EXPERIMENTAL_FILESYSTEM NLOHMANN_JSON_NAMESPACE_BEGIN
#include <experimental/filesystem>
namespace nlohmann::detail
{
namespace std_fs = std::experimental::filesystem;
} // namespace nlohmann::detail
#elif JSON_HAS_FILESYSTEM
#include <filesystem>
namespace nlohmann::detail
{
namespace std_fs = std::filesystem;
} // namespace nlohmann::detail
#endif

namespace nlohmann
{
namespace detail namespace detail
{ {

template<typename BasicJsonType> template<typename BasicJsonType>
inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{ {
Expand Down Expand Up @@ -491,6 +478,7 @@ struct from_json_fn
return from_json(j, std::forward<T>(val)); return from_json(j, std::forward<T>(val));
} }
}; };

} // namespace detail } // namespace detail


#ifndef JSON_HAS_CPP_17 #ifndef JSON_HAS_CPP_17
Expand All @@ -505,4 +493,5 @@ JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definition
#ifndef JSON_HAS_CPP_17 #ifndef JSON_HAS_CPP_17
} // namespace } // namespace
#endif #endif
} // namespace nlohmann
NLOHMANN_JSON_NAMESPACE_END
5 changes: 2 additions & 3 deletions include/nlohmann/detail/conversions/to_chars.hpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@


#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>


namespace nlohmann NLOHMANN_JSON_NAMESPACE_BEGIN
{
namespace detail namespace detail
{ {


Expand Down Expand Up @@ -1116,4 +1115,4 @@ char* to_chars(char* first, const char* last, FloatType value)
} }


} // namespace detail } // namespace detail
} // namespace nlohmann NLOHMANN_JSON_NAMESPACE_END
24 changes: 6 additions & 18 deletions include/nlohmann/detail/conversions/to_json.hpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,30 +17,17 @@
#include <valarray> // valarray #include <valarray> // valarray
#include <vector> // vector #include <vector> // vector


#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp> #include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/std_fs.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp> #include <nlohmann/detail/value_t.hpp>


#if JSON_HAS_EXPERIMENTAL_FILESYSTEM NLOHMANN_JSON_NAMESPACE_BEGIN
#include <experimental/filesystem>
namespace nlohmann::detail
{
namespace std_fs = std::experimental::filesystem;
} // namespace nlohmann::detail
#elif JSON_HAS_FILESYSTEM
#include <filesystem>
namespace nlohmann::detail
{
namespace std_fs = std::filesystem;
} // namespace nlohmann::detail
#endif

namespace nlohmann
{
namespace detail namespace detail
{ {

////////////////// //////////////////
// constructors // // constructors //
////////////////// //////////////////
Expand Down Expand Up @@ -449,4 +436,5 @@ JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-
#ifndef JSON_HAS_CPP_17 #ifndef JSON_HAS_CPP_17
} // namespace } // namespace
#endif #endif
} // namespace nlohmann
NLOHMANN_JSON_NAMESPACE_END
Loading