Fix conversion to std::optional (#4742)

* ⚗️ remove JSON_USE_IMPLICIT_CONVERSIONS check for from_json(json, std::optional)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* ⚗️ remove JSON_USE_IMPLICIT_CONVERSIONS check for from_json(json, std::optional)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* ⚗️ remove JSON_USE_IMPLICIT_CONVERSIONS check for from_json(json, std::optional)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* ⚗️ remove JSON_USE_IMPLICIT_CONVERSIONS check for from_json(json, std::optional)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* ⚗️ remove JSON_USE_IMPLICIT_CONVERSIONS check for from_json(json, std::optional)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* ⚗️ add C++ standard library as matrix option

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

*  remove inline

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann 2025-04-15 16:10:39 +02:00 committed by GitHub
parent 4cca3b9cb2
commit 96c1b52f1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 14 deletions

View File

@ -13,9 +13,6 @@
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
@ -32,6 +29,11 @@
#include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/value_t.hpp>
// include after macro_scope.hpp
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@ -47,7 +49,6 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
}
#ifdef JSON_HAS_CPP_17
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
@ -60,8 +61,6 @@ void from_json(const BasicJsonType& j, std::optional<T>& opt)
opt.emplace(j.template get<T>());
}
}
#endif // JSON_USE_IMPLICIT_CONVERSIONS
#endif // JSON_HAS_CPP_17
// overloads for basic_json template parameters

View File

@ -267,7 +267,7 @@ struct external_constructor<value_t::object>
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
{
if (opt.has_value())
{

View File

@ -173,9 +173,6 @@
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
@ -4817,6 +4814,11 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/value_t.hpp>
// include after macro_scope.hpp
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@ -4832,7 +4834,6 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
}
#ifdef JSON_HAS_CPP_17
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
@ -4845,8 +4846,6 @@ void from_json(const BasicJsonType& j, std::optional<T>& opt)
opt.emplace(j.template get<T>());
}
}
#endif // JSON_USE_IMPLICIT_CONVERSIONS
#endif // JSON_HAS_CPP_17
// overloads for basic_json template parameters
@ -5914,7 +5913,7 @@ struct external_constructor<value_t::object>
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
{
if (opt.has_value())
{

View File

@ -36,6 +36,14 @@ using ordered_json = nlohmann::ordered_json;
#include <variant>
#endif
#ifdef JSON_HAS_CPP_17
#if __has_include(<optional>)
#include <optional>
#elif __has_include(<experimental/optional>)
#include <experimental/optional>
#endif
#endif
#ifdef JSON_HAS_CPP_20
#if __has_include(<span>)
#include <span>
@ -390,6 +398,19 @@ struct Example_3810
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Example_3810, bla); // NOLINT(misc-use-internal-linkage)
/////////////////////////////////////////////////////////////////////
// for #4740
/////////////////////////////////////////////////////////////////////
#ifdef JSON_HAS_CPP_17
struct Example_4740
{
std::optional<std::string> host = std::nullopt;
std::optional<int> port = std::nullopt;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_4740, host, port)
};
#endif
TEST_CASE("regression tests 2")
{
SECTION("issue #1001 - Fix memory leak during parser callback")
@ -1037,6 +1058,28 @@ TEST_CASE("regression tests 2")
oj["test"] = states;
CHECK(oj["test"].dump() == expected);
}
#ifdef JSON_HAS_CPP_17
SECTION("issue #4740 - build issue with std::optional")
{
const auto t1 = Example_4740();
const auto j1 = nlohmann::json(t1);
CHECK(j1.dump() == "{\"host\":null,\"port\":null}");
const auto t2 = j1.get<Example_4740>();
CHECK(!t2.host.has_value());
CHECK(!t2.port.has_value());
// improve coverage
auto t3 = Example_4740();
t3.port = 80;
t3.host = "example.com";
const auto j2 = nlohmann::json(t3);
CHECK(j2.dump() == "{\"host\":\"example.com\",\"port\":80}");
const auto t4 = j2.get<Example_4740>();
CHECK(t4.host.has_value());
CHECK(t4.port.has_value());
}
#endif
}
DOCTEST_CLANG_SUPPRESS_WARNING_POP