Merge 14e3318929 into 0457de21cf
This commit is contained in:
commit
2a2e036647
@ -28,6 +28,7 @@
|
|||||||
#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>
|
||||||
|
#include <nlohmann/optional.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -43,6 +44,34 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
|||||||
n = nullptr;
|
n = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
void from_json(const BasicJsonType& j, std::optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (j.is_null())
|
||||||
|
{
|
||||||
|
opt = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt = j.template get<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
void from_json(const BasicJsonType& j, optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (j.is_null())
|
||||||
|
{
|
||||||
|
opt = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt = j.template get<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include <nlohmann/detail/meta/std_fs.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>
|
||||||
|
#include <nlohmann/optional.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -260,6 +261,29 @@ struct external_constructor<value_t::object>
|
|||||||
// to_json //
|
// to_json //
|
||||||
/////////////
|
/////////////
|
||||||
|
|
||||||
|
#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) noexcept
|
||||||
|
{
|
||||||
|
if (opt.has_value())
|
||||||
|
{
|
||||||
|
j = *opt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename T,
|
||||||
|
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
|
||||||
|
void to_json(BasicJsonType& j, const optional<T>& opt) noexcept
|
||||||
|
{
|
||||||
|
to_json(j, opt.base());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, T b) noexcept
|
inline void to_json(BasicJsonType& j, T b) noexcept
|
||||||
|
|||||||
224
include/nlohmann/optional.hpp
Normal file
224
include/nlohmann/optional.hpp
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class optional
|
||||||
|
{
|
||||||
|
// *INDENT-OFF*
|
||||||
|
|
||||||
|
using base_type = std::optional<T>;
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
template <typename U, typename = optional>
|
||||||
|
struct has_conversion_operator : std::false_type { };
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct has_conversion_operator<U,
|
||||||
|
decltype(std::declval<U>().operator optional())> : std::true_type { };
|
||||||
|
|
||||||
|
template <typename... U>
|
||||||
|
using is_base_constructible_from = std::is_constructible<base_type, U...>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using is_convertible_to_base = std::is_convertible<U, base_type>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using enable_int_if = std::enable_if_t<U::value, int>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_conversion_operator =
|
||||||
|
enable_int_if<
|
||||||
|
has_conversion_operator<U>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_implicit_forwarding =
|
||||||
|
enable_int_if<
|
||||||
|
std::conjunction<
|
||||||
|
std::negation<has_conversion_operator<U>>,
|
||||||
|
is_base_constructible_from<U>,
|
||||||
|
is_convertible_to_base<U>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_explicit_forwarding =
|
||||||
|
enable_int_if<
|
||||||
|
std::conjunction<
|
||||||
|
std::negation<has_conversion_operator<U>>,
|
||||||
|
is_base_constructible_from<U>,
|
||||||
|
std::negation<is_convertible_to_base<U>>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename... U>
|
||||||
|
using can_construct_in_place_from =
|
||||||
|
enable_int_if<
|
||||||
|
is_base_constructible_from<std::in_place_t, U...>
|
||||||
|
>;
|
||||||
|
|
||||||
|
struct noexcept_fix_t {}; // trick for GCC8.1 (see default constructor)
|
||||||
|
|
||||||
|
base_type base_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
base_type& base() & noexcept
|
||||||
|
{
|
||||||
|
return base_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const base_type& base() const & noexcept
|
||||||
|
{
|
||||||
|
return base_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_type&& base() && noexcept
|
||||||
|
{
|
||||||
|
return std::move(base_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr optional() noexcept(noexcept(std::optional<noexcept_fix_t>()))
|
||||||
|
: base_value() // explicitly initialized to mitigate -Werror=effc++
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr optional(std::nullopt_t /* unused */) noexcept
|
||||||
|
: base_value(std::nullopt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, use_conversion_operator<U> = 0>
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value).operator optional())
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value).operator optional())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U = T, use_implicit_forwarding<U> = 0>
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value))
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, use_explicit_forwarding<U> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value))
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename... Args, can_construct_in_place_from<U, Args...> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(std::in_place_t /* unused */, U&& u, Args&&... args)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::in_place, std::forward<U>(u), std::forward<Args>(args)...)
|
||||||
|
)) :
|
||||||
|
base_value(std::in_place, std::forward<U>(u), std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename... Args, can_construct_in_place_from<std::initializer_list<U>&, Args...> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(std::in_place_t /* unused */, std::initializer_list<U> u, Args&&... args)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::in_place, u, std::forward<Args>(args)...)
|
||||||
|
)) :
|
||||||
|
base_value(std::in_place, u, std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T& operator *() & noexcept { return *base_value; }
|
||||||
|
constexpr const T& operator *() const& noexcept { return *base_value; }
|
||||||
|
|
||||||
|
constexpr T&& operator *() && noexcept { return static_cast<T&&>(*base_value); }
|
||||||
|
constexpr const T&& operator *() const&& noexcept { return static_cast<const T&&>(*base_value); }
|
||||||
|
|
||||||
|
constexpr T* operator ->() noexcept { return base_value.operator ->(); }
|
||||||
|
constexpr const T* operator ->() const noexcept { return base_value.operator ->(); }
|
||||||
|
|
||||||
|
operator base_type& () & noexcept { return base_value; }
|
||||||
|
operator base_type&& () && noexcept { return std::move(base_value); }
|
||||||
|
|
||||||
|
// *INDENT-ON*
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail::opt
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T> const T& cmp_val(const T& v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template <typename T> const std::optional<T>& cmp_val(const optional<T>& v)
|
||||||
|
{
|
||||||
|
return v.base();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail::opt
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON_EXPR(OP) \
|
||||||
|
detail::opt::cmp_val(lhs) OP detail::opt::cmp_val(rhs)
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON(OP, LHS, RHS) \
|
||||||
|
template <typename A, typename B> \
|
||||||
|
auto operator OP (const LHS& lhs, const RHS& rhs) \
|
||||||
|
-> decltype(JSON_OPTIONAL_COMPARISON_EXPR(OP)) \
|
||||||
|
{ \
|
||||||
|
return JSON_OPTIONAL_COMPARISON_EXPR(OP); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
// *INDENT-OFF*
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON( <=>, optional<A>, B)
|
||||||
|
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, optional<A>, B)
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, optional<A>, std::optional<B>)
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, std::optional<A>, optional<B>)
|
||||||
|
|
||||||
|
#else // JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON_OP(OP) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, std::optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, std::optional<A>, optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, B) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, A, optional<B>)
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( == )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( != )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( < )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( <= )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( > )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( >= )
|
||||||
|
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON_OP
|
||||||
|
|
||||||
|
#endif // JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON_EXPR
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // JSON_HAS_CPP_17
|
||||||
@ -4655,6 +4655,233 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/value_t.hpp>
|
// #include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/optional.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class optional
|
||||||
|
{
|
||||||
|
// *INDENT-OFF*
|
||||||
|
|
||||||
|
using base_type = std::optional<T>;
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
template <typename U, typename = optional>
|
||||||
|
struct has_conversion_operator : std::false_type { };
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct has_conversion_operator<U,
|
||||||
|
decltype(std::declval<U>().operator optional())> : std::true_type { };
|
||||||
|
|
||||||
|
template <typename... U>
|
||||||
|
using is_base_constructible_from = std::is_constructible<base_type, U...>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using is_convertible_to_base = std::is_convertible<U, base_type>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using enable_int_if = std::enable_if_t<U::value, int>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_conversion_operator =
|
||||||
|
enable_int_if<
|
||||||
|
has_conversion_operator<U>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_implicit_forwarding =
|
||||||
|
enable_int_if<
|
||||||
|
std::conjunction<
|
||||||
|
std::negation<has_conversion_operator<U>>,
|
||||||
|
is_base_constructible_from<U>,
|
||||||
|
is_convertible_to_base<U>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using use_explicit_forwarding =
|
||||||
|
enable_int_if<
|
||||||
|
std::conjunction<
|
||||||
|
std::negation<has_conversion_operator<U>>,
|
||||||
|
is_base_constructible_from<U>,
|
||||||
|
std::negation<is_convertible_to_base<U>>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename... U>
|
||||||
|
using can_construct_in_place_from =
|
||||||
|
enable_int_if<
|
||||||
|
is_base_constructible_from<std::in_place_t, U...>
|
||||||
|
>;
|
||||||
|
|
||||||
|
struct noexcept_fix_t {}; // trick for GCC8.1 (see default constructor)
|
||||||
|
|
||||||
|
base_type base_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
base_type& base() & noexcept
|
||||||
|
{
|
||||||
|
return base_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const base_type& base() const & noexcept
|
||||||
|
{
|
||||||
|
return base_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_type&& base() && noexcept
|
||||||
|
{
|
||||||
|
return std::move(base_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr optional() noexcept(noexcept(std::optional<noexcept_fix_t>()))
|
||||||
|
: base_value() // explicitly initialized to mitigate -Werror=effc++
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr optional(std::nullopt_t /* unused */) noexcept
|
||||||
|
: base_value(std::nullopt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, use_conversion_operator<U> = 0>
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value).operator optional())
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value).operator optional())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U = T, use_implicit_forwarding<U> = 0>
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value))
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, use_explicit_forwarding<U> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(U&& value)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::forward<U>(value))
|
||||||
|
)) :
|
||||||
|
base_value(std::forward<U>(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename... Args, can_construct_in_place_from<U, Args...> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(std::in_place_t /* unused */, U&& u, Args&&... args)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::in_place, std::forward<U>(u), std::forward<Args>(args)...)
|
||||||
|
)) :
|
||||||
|
base_value(std::in_place, std::forward<U>(u), std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename... Args, can_construct_in_place_from<std::initializer_list<U>&, Args...> = 0>
|
||||||
|
explicit
|
||||||
|
constexpr optional(std::in_place_t /* unused */, std::initializer_list<U> u, Args&&... args)
|
||||||
|
noexcept(noexcept(
|
||||||
|
base_type(std::in_place, u, std::forward<Args>(args)...)
|
||||||
|
)) :
|
||||||
|
base_value(std::in_place, u, std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T& operator *() & noexcept { return *base_value; }
|
||||||
|
constexpr const T& operator *() const& noexcept { return *base_value; }
|
||||||
|
|
||||||
|
constexpr T&& operator *() && noexcept { return static_cast<T&&>(*base_value); }
|
||||||
|
constexpr const T&& operator *() const&& noexcept { return static_cast<const T&&>(*base_value); }
|
||||||
|
|
||||||
|
constexpr T* operator ->() noexcept { return base_value.operator ->(); }
|
||||||
|
constexpr const T* operator ->() const noexcept { return base_value.operator ->(); }
|
||||||
|
|
||||||
|
operator base_type& () & noexcept { return base_value; }
|
||||||
|
operator base_type&& () && noexcept { return std::move(base_value); }
|
||||||
|
|
||||||
|
// *INDENT-ON*
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail::opt
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T> const T& cmp_val(const T& v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
template <typename T> const std::optional<T>& cmp_val(const optional<T>& v)
|
||||||
|
{
|
||||||
|
return v.base();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail::opt
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON_EXPR(OP) \
|
||||||
|
detail::opt::cmp_val(lhs) OP detail::opt::cmp_val(rhs)
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON(OP, LHS, RHS) \
|
||||||
|
template <typename A, typename B> \
|
||||||
|
auto operator OP (const LHS& lhs, const RHS& rhs) \
|
||||||
|
-> decltype(JSON_OPTIONAL_COMPARISON_EXPR(OP)) \
|
||||||
|
{ \
|
||||||
|
return JSON_OPTIONAL_COMPARISON_EXPR(OP); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
// *INDENT-OFF*
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON( <=>, optional<A>, B)
|
||||||
|
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, optional<A>, B)
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, optional<A>, std::optional<B>)
|
||||||
|
JSON_OPTIONAL_COMPARISON( ==, std::optional<A>, optional<B>)
|
||||||
|
|
||||||
|
#else // JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
#define JSON_OPTIONAL_COMPARISON_OP(OP) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, std::optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, std::optional<A>, optional<B>) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, optional<A>, B) \
|
||||||
|
JSON_OPTIONAL_COMPARISON(OP, A, optional<B>)
|
||||||
|
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( == )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( != )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( < )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( <= )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( > )
|
||||||
|
JSON_OPTIONAL_COMPARISON_OP( >= )
|
||||||
|
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON_OP
|
||||||
|
|
||||||
|
#endif // JSON_HAS_CPP_20
|
||||||
|
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON
|
||||||
|
#undef JSON_OPTIONAL_COMPARISON_EXPR
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // JSON_HAS_CPP_17
|
||||||
|
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -4670,6 +4897,34 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
|||||||
n = nullptr;
|
n = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
void from_json(const BasicJsonType& j, std::optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (j.is_null())
|
||||||
|
{
|
||||||
|
opt = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt = j.template get<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
void from_json(const BasicJsonType& j, optional<T>& opt)
|
||||||
|
{
|
||||||
|
if (j.is_null())
|
||||||
|
{
|
||||||
|
opt = std::nullopt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt = j.template get<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||||
@ -5400,6 +5655,8 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
|
|||||||
|
|
||||||
// #include <nlohmann/detail/value_t.hpp>
|
// #include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/optional.hpp>
|
||||||
|
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -5637,6 +5894,29 @@ struct external_constructor<value_t::object>
|
|||||||
// to_json //
|
// to_json //
|
||||||
/////////////
|
/////////////
|
||||||
|
|
||||||
|
#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) noexcept
|
||||||
|
{
|
||||||
|
if (opt.has_value())
|
||||||
|
{
|
||||||
|
j = *opt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename T,
|
||||||
|
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
|
||||||
|
void to_json(BasicJsonType& j, const optional<T>& opt) noexcept
|
||||||
|
{
|
||||||
|
to_json(j, opt.base());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, T b) noexcept
|
inline void to_json(BasicJsonType& j, T b) noexcept
|
||||||
|
|||||||
@ -31,6 +31,15 @@ using nlohmann::json;
|
|||||||
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
|
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
|
||||||
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
||||||
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
|
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
|
||||||
|
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-macros")
|
||||||
|
|
||||||
|
// For testing copy-initialization of std::optional and nlohmann::optional
|
||||||
|
// (clang doesn't need the suppressing)
|
||||||
|
#define SUPPRESS_CONVERSION_WARNING \
|
||||||
|
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wconversion")
|
||||||
|
|
||||||
|
#define RESTORE_CONVERSION_WARNING \
|
||||||
|
DOCTEST_GCC_SUPPRESS_WARNING_POP
|
||||||
|
|
||||||
TEST_CASE("value conversion")
|
TEST_CASE("value conversion")
|
||||||
{
|
{
|
||||||
@ -1569,4 +1578,147 @@ TEST_CASE("JSON to enum mapping")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
TEST_CASE("std::optional")
|
||||||
|
{
|
||||||
|
SECTION("null")
|
||||||
|
{
|
||||||
|
json j_null;
|
||||||
|
std::optional<std::string> const opt_null;
|
||||||
|
|
||||||
|
CHECK(json(opt_null) == j_null);
|
||||||
|
CHECK(j_null.get<std::optional<std::string>>() == std::nullopt);
|
||||||
|
|
||||||
|
using opt_int = std::optional<int>;
|
||||||
|
|
||||||
|
auto opt1 = []() -> opt_int { return json().get<opt_int>(); };
|
||||||
|
auto opt2 = []() -> opt_int { return opt_int(json()); }; // NOLINT(modernize-return-braced-init-list)
|
||||||
|
|
||||||
|
CHECK(opt1() == std::nullopt);
|
||||||
|
CHECK_THROWS_AS(opt2(), json::type_error&);
|
||||||
|
|
||||||
|
#if JSON_USE_IMPLICIT_CONVERSIONS
|
||||||
|
SUPPRESS_CONVERSION_WARNING
|
||||||
|
auto opt3 = []() -> opt_int { return json(); };
|
||||||
|
RESTORE_CONVERSION_WARNING
|
||||||
|
CHECK_THROWS_AS(opt3(), json::type_error&);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string")
|
||||||
|
{
|
||||||
|
json j_string = "string";
|
||||||
|
std::optional<std::string> opt_string = "string";
|
||||||
|
|
||||||
|
CHECK(json(opt_string) == j_string);
|
||||||
|
CHECK(std::optional<std::string>(j_string) == opt_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bool")
|
||||||
|
{
|
||||||
|
json j_bool = true;
|
||||||
|
std::optional<bool> opt_bool = true;
|
||||||
|
|
||||||
|
CHECK(json(opt_bool) == j_bool);
|
||||||
|
CHECK(std::optional<bool>(j_bool) == opt_bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("number")
|
||||||
|
{
|
||||||
|
json j_number = 1;
|
||||||
|
std::optional<int> opt_int = 1;
|
||||||
|
|
||||||
|
CHECK(json(opt_int) == j_number);
|
||||||
|
CHECK(std::optional<int>(j_number) == opt_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
json j_array = {1, 2, nullptr};
|
||||||
|
std::vector<std::optional<int>> opt_array = {{1, 2, std::nullopt}};
|
||||||
|
|
||||||
|
CHECK(json(opt_array) == j_array);
|
||||||
|
CHECK(j_array.get<std::vector<std::optional<int>>>() == opt_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("object")
|
||||||
|
{
|
||||||
|
json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
|
||||||
|
std::map<std::string, std::optional<int>> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
|
||||||
|
|
||||||
|
CHECK(json(opt_object) == j_object);
|
||||||
|
CHECK(j_object.get<std::map<std::string, std::optional<int>>>() == opt_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("nlohmann::optional")
|
||||||
|
{
|
||||||
|
SECTION("null")
|
||||||
|
{
|
||||||
|
json j_null;
|
||||||
|
nlohmann::optional<std::string> const opt_null;
|
||||||
|
|
||||||
|
CHECK(json(opt_null) == j_null);
|
||||||
|
CHECK(j_null.get<nlohmann::optional<std::string>>() == std::nullopt);
|
||||||
|
|
||||||
|
using opt_int = nlohmann::optional<int>;
|
||||||
|
|
||||||
|
auto opt1 = []() -> opt_int { return json().get<opt_int>(); };
|
||||||
|
auto opt2 = []() -> opt_int { return opt_int(json()); }; // NOLINT(modernize-return-braced-init-list)
|
||||||
|
SUPPRESS_CONVERSION_WARNING
|
||||||
|
auto opt3 = []() -> opt_int { return json(); };
|
||||||
|
RESTORE_CONVERSION_WARNING
|
||||||
|
|
||||||
|
CHECK(opt1() == std::nullopt);
|
||||||
|
CHECK(opt2() == std::nullopt);
|
||||||
|
CHECK(opt3() == std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string")
|
||||||
|
{
|
||||||
|
json j_string = "string";
|
||||||
|
nlohmann::optional<std::string> opt_string = "string";
|
||||||
|
|
||||||
|
CHECK(json(opt_string) == j_string);
|
||||||
|
CHECK(nlohmann::optional<std::string>(j_string) == opt_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("bool")
|
||||||
|
{
|
||||||
|
json j_bool = true;
|
||||||
|
nlohmann::optional<bool> opt_bool = true;
|
||||||
|
|
||||||
|
CHECK(json(opt_bool) == j_bool);
|
||||||
|
CHECK(nlohmann::optional<bool>(j_bool) == opt_bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("number")
|
||||||
|
{
|
||||||
|
json j_number = 1;
|
||||||
|
nlohmann::optional<int> opt_int = 1;
|
||||||
|
|
||||||
|
CHECK(json(opt_int) == j_number);
|
||||||
|
CHECK(nlohmann::optional<int>(j_number) == opt_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
json j_array = {1, 2, nullptr};
|
||||||
|
std::vector<nlohmann::optional<int>> opt_array = {{1, 2, std::nullopt}};
|
||||||
|
|
||||||
|
CHECK(json(opt_array) == j_array);
|
||||||
|
CHECK(j_array.get<std::vector<nlohmann::optional<int>>>() == opt_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("object")
|
||||||
|
{
|
||||||
|
json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
|
||||||
|
std::map<std::string, nlohmann::optional<int>> opt_object{{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
|
||||||
|
|
||||||
|
CHECK(json(opt_object) == j_object);
|
||||||
|
CHECK(j_object.get<std::map<std::string, nlohmann::optional<int>>>() == opt_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DOCTEST_CLANG_SUPPRESS_WARNING_POP
|
DOCTEST_CLANG_SUPPRESS_WARNING_POP
|
||||||
|
|||||||
181
tests/src/unit-optional.cpp
Normal file
181
tests/src/unit-optional.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#ifdef JSON_HAS_CPP_17
|
||||||
|
|
||||||
|
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
|
||||||
|
DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using std::nullopt;
|
||||||
|
using std::in_place;
|
||||||
|
using nlohmann::optional;
|
||||||
|
|
||||||
|
using opt_int = optional<int>;
|
||||||
|
using opt_vec = optional<std::vector<int>>;
|
||||||
|
using opt_ptr = optional<std::unique_ptr<int>>;
|
||||||
|
|
||||||
|
using std_opt_int = std::optional<int>;
|
||||||
|
using std_opt_vec = std::optional<std::vector<int>>;
|
||||||
|
using std_opt_ptr = std::optional<std::unique_ptr<int>>;
|
||||||
|
|
||||||
|
// NOLINTBEGIN(bugprone-unchecked-optional-access,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
|
||||||
|
|
||||||
|
TEST_CASE("nlohmann::optional comparison")
|
||||||
|
{
|
||||||
|
CHECK(opt_int() == nullopt);
|
||||||
|
CHECK(nullopt == opt_int());
|
||||||
|
CHECK(opt_int() == opt_int(nullopt));
|
||||||
|
CHECK(opt_int(0) == opt_int(0));
|
||||||
|
CHECK_FALSE(opt_int(0) == nullopt);
|
||||||
|
CHECK_FALSE(nullopt == opt_int(0));
|
||||||
|
CHECK_FALSE(opt_int(0) == opt_int(1));
|
||||||
|
|
||||||
|
CHECK(opt_int() == std_opt_int());
|
||||||
|
CHECK(opt_int(0) == std_opt_int(0));
|
||||||
|
CHECK_FALSE(opt_int(0) == std_opt_int(1));
|
||||||
|
|
||||||
|
CHECK(std_opt_int() == opt_int());
|
||||||
|
CHECK(std_opt_int(0) == opt_int(0));
|
||||||
|
CHECK_FALSE(std_opt_int(0) == opt_int(1));
|
||||||
|
|
||||||
|
CHECK(opt_int(0) != nullopt);
|
||||||
|
CHECK(nullopt != opt_int(0));
|
||||||
|
CHECK(opt_int(0) != opt_int(1));
|
||||||
|
CHECK_FALSE(opt_int() != nullopt);
|
||||||
|
CHECK_FALSE(nullopt != opt_int());
|
||||||
|
CHECK_FALSE(opt_int() != opt_int(nullopt));
|
||||||
|
CHECK_FALSE(opt_int(0) != opt_int(0));
|
||||||
|
|
||||||
|
CHECK_FALSE(opt_int() != std_opt_int());
|
||||||
|
CHECK_FALSE(opt_int(0) != std_opt_int(0));
|
||||||
|
CHECK(opt_int(0) != std_opt_int(1));
|
||||||
|
|
||||||
|
CHECK_FALSE(std_opt_int() != opt_int());
|
||||||
|
CHECK_FALSE(std_opt_int(0) != opt_int(0));
|
||||||
|
CHECK(std_opt_int(0) != opt_int(1));
|
||||||
|
|
||||||
|
CHECK(opt_int(0) > nullopt);
|
||||||
|
CHECK(opt_int(1) > opt_int(0));
|
||||||
|
CHECK_FALSE(nullopt > opt_int(0));
|
||||||
|
CHECK_FALSE(opt_int(0) > opt_int(1));
|
||||||
|
|
||||||
|
CHECK(opt_int(0) > std_opt_int());
|
||||||
|
CHECK(std_opt_int(0) > opt_int());
|
||||||
|
|
||||||
|
CHECK(opt_int(0) >= nullopt);
|
||||||
|
CHECK(opt_int(1) >= opt_int(0));
|
||||||
|
CHECK_FALSE(nullopt >= opt_int(0));
|
||||||
|
CHECK_FALSE(opt_int(0) >= opt_int(1));
|
||||||
|
|
||||||
|
CHECK(opt_int(0) >= std_opt_int());
|
||||||
|
CHECK(std_opt_int(0) >= opt_int());
|
||||||
|
|
||||||
|
CHECK(nullopt < opt_int(0));
|
||||||
|
CHECK(opt_int(0) < opt_int(1));
|
||||||
|
CHECK_FALSE(opt_int(0) < nullopt);
|
||||||
|
CHECK_FALSE(opt_int(1) < opt_int(0));
|
||||||
|
|
||||||
|
CHECK_FALSE(opt_int(0) < std_opt_int());
|
||||||
|
CHECK_FALSE(std_opt_int(0) < opt_int());
|
||||||
|
|
||||||
|
CHECK(nullopt <= opt_int(0));
|
||||||
|
CHECK(opt_int(0) <= opt_int(1));
|
||||||
|
CHECK_FALSE(opt_int(0) <= nullopt);
|
||||||
|
CHECK_FALSE(opt_int(1) <= opt_int(0));
|
||||||
|
|
||||||
|
CHECK_FALSE(opt_int(0) <= std_opt_int());
|
||||||
|
CHECK_FALSE(std_opt_int(0) <= opt_int());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("nlohmann::optional constructors")
|
||||||
|
{
|
||||||
|
struct S1
|
||||||
|
{
|
||||||
|
operator int() noexcept
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct S2 : S1
|
||||||
|
{
|
||||||
|
operator opt_int() noexcept
|
||||||
|
{
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CHECK(opt_int(S1()) == opt_int(0));
|
||||||
|
CHECK(opt_int(S2()) == nullopt);
|
||||||
|
|
||||||
|
CHECK(opt_int(S1()) == std_opt_int(S1()));
|
||||||
|
CHECK(opt_int(S2()) != std_opt_int(S2()));
|
||||||
|
|
||||||
|
CHECK(opt_int(std_opt_int(0)) == opt_int(0));
|
||||||
|
CHECK(std_opt_int(opt_int(0)) == opt_int(0));
|
||||||
|
|
||||||
|
CHECK(opt_int(in_place) == std_opt_int(in_place));
|
||||||
|
CHECK(opt_vec(in_place) == std_opt_vec(in_place));
|
||||||
|
CHECK(opt_ptr(in_place) == std_opt_ptr(in_place));
|
||||||
|
|
||||||
|
CHECK(opt_vec(in_place, 5)->size() == 5);
|
||||||
|
CHECK(opt_vec(in_place, {1, 2, 3}) == std_opt_vec(in_place, {1, 2, 3}));
|
||||||
|
CHECK(**opt_ptr(in_place, new int{42}) == **std_opt_ptr(in_place, new int{42}));
|
||||||
|
|
||||||
|
std::vector<int> vec{1, 2, 3};
|
||||||
|
CHECK(*opt_vec(in_place, vec.begin(), vec.end()) == vec);
|
||||||
|
|
||||||
|
CHECK(opt_vec({1, 2, 3})->size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("nlohmann::optional copy")
|
||||||
|
{
|
||||||
|
opt_int opt1 = 111;
|
||||||
|
std_opt_int opt2 = 222;
|
||||||
|
|
||||||
|
SECTION("1")
|
||||||
|
{
|
||||||
|
opt1 = std::as_const(opt2);
|
||||||
|
CHECK(*opt1 == 222);
|
||||||
|
CHECK(*opt_int(std::as_const(opt1).base()) == 222);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("2")
|
||||||
|
{
|
||||||
|
opt2 = std::as_const(opt1).base();
|
||||||
|
CHECK(*opt2 == 111);
|
||||||
|
CHECK(*opt_int(std::as_const(opt2)) == 111);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("nlohmann::optional move")
|
||||||
|
{
|
||||||
|
opt_ptr opt1(new int(111));
|
||||||
|
std_opt_ptr opt2(new int(222));
|
||||||
|
|
||||||
|
SECTION("1")
|
||||||
|
{
|
||||||
|
opt1 = std::move(opt2);
|
||||||
|
CHECK(*opt2 == nullptr);
|
||||||
|
CHECK(**opt1 == 222);
|
||||||
|
CHECK(**opt_ptr(std::move(opt1)) == 222);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("2")
|
||||||
|
{
|
||||||
|
opt2 = std::move(opt1);
|
||||||
|
CHECK(*opt1 == nullptr);
|
||||||
|
CHECK(**opt2 == 111);
|
||||||
|
CHECK(**opt_ptr(std::move(opt2)) == 111);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOLINTEND(bugprone-unchecked-optional-access,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
|
||||||
|
|
||||||
|
DOCTEST_GCC_SUPPRESS_WARNING_POP
|
||||||
|
|
||||||
|
#endif // JSON_HAS_CPP_17
|
||||||
Loading…
Reference in New Issue
Block a user