json/include/nlohmann/optional.hpp

226 lines
6.1 KiB
C++
Raw Normal View History

2021-08-28 19:31:45 +03:00
#pragma once
#include <nlohmann/detail/macro_scope.hpp>
#ifdef JSON_HAS_CPP_17
#include <optional>
#include <utility>
NLOHMANN_JSON_NAMESPACE_BEGIN
2021-08-28 19:31:45 +03:00
template <typename T>
class optional
2021-08-28 19:31:45 +03:00
{
// *INDENT-OFF*
using base_type = std::optional<T>;
using value_type = T;
2021-08-28 19:31:45 +03:00
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...>
>;
2023-01-08 10:00:04 +03:00
struct noexcept_fix_t {}; // trick for GCC8.1 (see default constructor)
2021-08-28 19:31:45 +03:00
base_type base_value;
2021-08-28 19:31:45 +03:00
public:
2023-01-08 09:55:55 +03:00
base_type& base() & noexcept
{
return base_value;
}
2023-01-08 09:55:55 +03:00
const base_type& base() const & noexcept
2021-08-28 19:31:45 +03:00
{
return base_value;
}
2023-01-08 09:55:55 +03:00
base_type&& base() && noexcept
{
return std::move(base_value);
2021-08-28 19:31:45 +03:00
}
constexpr optional() noexcept(noexcept(std::optional<noexcept_fix_t>()))
: base_value() // explicitly initialized to mitigate -Werror=effc++
{
}
2021-08-28 19:31:45 +03:00
constexpr optional(std::nullopt_t /* unused */) noexcept
: base_value(std::nullopt)
2021-08-28 19:31:45 +03:00
{
}
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())
2021-08-28 19:31:45 +03:00
{
}
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))
2021-08-28 19:31:45 +03:00
{
}
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))
2021-08-28 19:31:45 +03:00
{
}
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)...)
2021-08-28 19:31:45 +03:00
{
}
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)...)
2021-08-28 19:31:45 +03:00
{
}
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 ->(); }
2023-01-08 09:55:55 +03:00
operator base_type& () & noexcept { return base_value; }
operator base_type&& () && noexcept { return std::move(base_value); }
2021-08-28 19:31:45 +03:00
// *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
2023-01-08 15:35:08 +03:00
#define JSON_OPTIONAL_COMPARISON_EXPR(OP) \
detail::opt::cmp_val(lhs) OP detail::opt::cmp_val(rhs)
2023-01-08 15:35:08 +03:00
#define JSON_OPTIONAL_COMPARISON(OP, LHS, RHS) \
template <typename A, typename B> \
auto operator OP (const LHS& lhs, const RHS& rhs) \
noexcept(noexcept(JSON_OPTIONAL_COMPARISON_EXPR(OP))) \
-> decltype(JSON_OPTIONAL_COMPARISON_EXPR(OP)) \
{ \
return JSON_OPTIONAL_COMPARISON_EXPR(OP); \
}
#ifdef JSON_HAS_CPP_20
// *INDENT-OFF*
2023-01-08 15:35:08 +03:00
JSON_OPTIONAL_COMPARISON( <=>, optional<A>, B)
// *INDENT-ON*
2023-01-08 15:35:08 +03:00
JSON_OPTIONAL_COMPARISON( ==, optional<A>, B)
JSON_OPTIONAL_COMPARISON( ==, optional<A>, std::optional<B>)
JSON_OPTIONAL_COMPARISON( ==, std::optional<A>, optional<B>)
2023-01-08 15:35:08 +03:00
#else // JSON_HAS_CPP_20
2023-01-08 15:35:08 +03:00
#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>)
2023-01-08 15:35:08 +03:00
JSON_OPTIONAL_COMPARISON_OP( == )
JSON_OPTIONAL_COMPARISON_OP( != )
JSON_OPTIONAL_COMPARISON_OP( < )
JSON_OPTIONAL_COMPARISON_OP( <= )
JSON_OPTIONAL_COMPARISON_OP( > )
JSON_OPTIONAL_COMPARISON_OP( >= )
2021-08-28 19:31:45 +03:00
2023-01-08 15:35:08 +03:00
#undef JSON_OPTIONAL_COMPARISON_OP
#endif // JSON_HAS_CPP_20
2023-01-08 15:35:08 +03:00
#undef JSON_OPTIONAL_COMPARISON
#undef JSON_OPTIONAL_COMPARISON_EXPR
NLOHMANN_JSON_NAMESPACE_END
2021-08-28 19:31:45 +03:00
#endif // JSON_HAS_CPP_17