-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
998a9d0
commit b7a5d99
Showing
6 changed files
with
616 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#pragma once | ||
|
||
#include <nlohmann/detail/macro_scope.hpp> | ||
|
||
#ifdef JSON_HAS_CPP_17 | ||
|
||
#include <optional> | ||
#include <utility> | ||
|
||
namespace nlohmann | ||
{ | ||
|
||
template <typename T> | ||
class optional : public std::optional<T> | ||
{ | ||
// *INDENT-OFF* | ||
|
||
using base_type = std::optional<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...> | ||
>; | ||
|
||
public: | ||
|
||
const base_type& base() const | ||
{ | ||
return *this; | ||
} | ||
|
||
constexpr optional() noexcept = default; | ||
|
||
constexpr optional(std::nullopt_t) noexcept | ||
: base_type(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_type(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_type(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_type(std::forward<U>(value)) | ||
{ | ||
} | ||
|
||
template <typename U, typename... Args, can_construct_in_place_from<U, Args...> = 0> | ||
explicit | ||
constexpr optional(std::in_place_t, U&& u, Args&&... args) | ||
noexcept(noexcept( | ||
base_type(std::in_place, std::forward<U>(u), std::forward<Args>(args)...) | ||
)) : | ||
base_type(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, std::initializer_list<U> u, Args&&... args) | ||
noexcept(noexcept( | ||
base_type(std::in_place, u, std::forward<Args>(args)...) | ||
)) : | ||
base_type(std::in_place, u, std::forward<Args>(args)...) | ||
{ | ||
} | ||
|
||
// *INDENT-ON* | ||
}; | ||
|
||
template<class T, class U> | ||
constexpr bool operator == (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() == rhs.base(); | ||
} | ||
|
||
template<class T, class U> | ||
constexpr bool operator != (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() != rhs.base(); | ||
} | ||
|
||
template<class T, class U> | ||
constexpr bool operator < (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() < rhs.base(); | ||
} | ||
|
||
template<class T, class U> | ||
constexpr bool operator <= (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() <= rhs.base(); | ||
} | ||
|
||
template<class T, class U> | ||
constexpr bool operator > (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() > rhs.base(); | ||
} | ||
|
||
template<class T, class U> | ||
constexpr bool operator >= (const optional<T>& lhs, const optional<U>& rhs) | ||
{ | ||
return lhs.base() >= rhs.base(); | ||
} | ||
|
||
} // namespace nlohmann | ||
|
||
#endif // JSON_HAS_CPP_17 |
Oops, something went wrong.