// optional standard header
// Copyright (c) Microsoft Corporation. All rights reserved.
#pragma once
#ifndef _OPTIONAL_
#define _OPTIONAL_
#ifndef RC_INVOKED
#include <yvals.h>

#if _HAS_CXX17
#include <exception>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <xmemory0>
#include <xsmf_control.h>

 #pragma pack(push,_CRT_PACKING)
 #pragma warning(push,_STL_WARNING_LEVEL)
 #pragma warning(disable: _STL_DISABLED_WARNINGS)
 _STL_DISABLE_CLANG_WARNINGS
 #pragma push_macro("new")
 #undef new

_STD_BEGIN

		// STRUCT nullopt_t [optional.nullopt]
struct nullopt_t
	{	// no-value state indicator
	struct _Tag {};
	constexpr explicit nullopt_t(_Tag) {}
	};
_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::_Tag{}};

		// CLASS bad_optional_access [optional.bad_optional_access]
class bad_optional_access
	: public exception
	{
public:
	_NODISCARD virtual const char * __CLR_OR_THIS_CALL what() const noexcept override
		{
		return ("Bad optional access");
		}

 #if !_HAS_EXCEPTIONS
protected:
	virtual void _Doraise() const
		{	// perform class-specific exception handling
		_RAISE(*this);
		}
 #endif /* !_HAS_EXCEPTIONS */
	};

template<class _Ty,
	bool = is_trivially_destructible_v<_Ty>>
	struct _Optional_destruct_base
	{	// either contains a value of _Ty or is empty (trivial destructor)
	union
		{
		char _Dummy;
		remove_const_t<_Ty> _Value;
		};
	bool _Has_value;

	constexpr _Optional_destruct_base() noexcept
		: _Dummy{}, _Has_value{false}
		{	// initialize an empty optional
		}

	template<class... _Types>
		constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args)
		: _Value(_STD forward<_Types>(_Args)...), _Has_value{true}
		{	// initialize contained value with _Args...
		}

	void reset() noexcept
		{	// destroy any contained value and transition to the empty state
		this->_Has_value = false;
		}
	};

template<class _Ty>
	struct _Optional_destruct_base<_Ty, false>
	{	// either contains a value of _Ty or is empty (non-trivial destructor)
	union
		{
		char _Dummy;
		remove_const_t<_Ty> _Value;
		};
	bool _Has_value;

	~_Optional_destruct_base() noexcept
		{	// destroy any contained value
		if (_Has_value)
			{
			_Destroy_in_place(_Value);
			}
		}

	constexpr _Optional_destruct_base() noexcept
		: _Dummy{}, _Has_value{false}
		{	// initialize an empty optional
		}

	template<class... _Types>
		constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args)
		: _Value(_STD forward<_Types>(_Args)...), _Has_value{true}
		{	// initialize contained value with _Args...
		}

	_Optional_destruct_base(const _Optional_destruct_base&) = default;
	_Optional_destruct_base(_Optional_destruct_base&&) = default;
	_Optional_destruct_base& operator=(const _Optional_destruct_base&) = default;
	_Optional_destruct_base& operator=(_Optional_destruct_base&&) = default;

	void reset() noexcept
		{	// destroy any contained value and transition to the empty state
		if (this->_Has_value)
			{
			_Destroy_in_place(this->_Value);
			this->_Has_value = false;
			}
		}
	};

template<class _Ty>
	struct _Optional_construct_base
		: _Optional_destruct_base<_Ty>
	{	// Layer common behaviors atop the _Optional_destruct_base implementations
	using _Optional_destruct_base<_Ty>::_Optional_destruct_base;

	template<class... _Types>
		_Ty& _Construct(_Types&&... _Args)
		{	// transition from the empty to the value-containing state
			// pre: !this->_Has_value
		_Construct_in_place(this->_Value, _STD forward<_Types>(_Args)...);
		this->_Has_value = true;
		return (this->_Value);
		}

	template<class _Ty2>
		void _Assign(_Ty2&& _Right)
		{	// assign / initialize the contained value from _Right
		if (this->_Has_value)
			{
			this->_Value = _STD forward<_Ty2>(_Right);
			}
		else
			{
			_Construct(_STD forward<_Ty2>(_Right));
			}
		}

	template<class _Self>
		void _Construct_from(_Self&& _Right)
			_NOEXCEPT_COND(is_nothrow_constructible_v<_Ty, decltype((_STD forward<_Self>(_Right)._Value))>)
		{	// initialize contained value from _Right iff it contains a value
		if (_Right._Has_value)
			{
			_Construct(_STD forward<_Self>(_Right)._Value);
			}
		}

	template<class _Self>
		void _Assign_from(_Self&& _Right)
			_NOEXCEPT_COND(is_nothrow_constructible_v<_Ty, decltype((_STD forward<_Self>(_Right)._Value))>
				&& is_nothrow_assignable_v<_Ty&, decltype((_STD forward<_Self>(_Right)._Value))>)
		{	// assign/initialize/destroy contained value from _Right
		if (_Right._Has_value)
			{
			_Assign(_STD forward<_Self>(_Right)._Value);
			}
		else
			{
			this->reset();
			}
		}

	constexpr _Ty& _Get() & noexcept
		{
		return (this->_Value);
		}
	constexpr const _Ty& _Get() const & noexcept
		{
		return (this->_Value);
		}
	};

		// CLASS TEMPLATE optional [optional.object]
template<class _Ty>
	class optional
		: private _SMF_control<_Optional_construct_base<_Ty>, _Ty>
	{	// optional for object types
private:
	using _Mybase = _SMF_control<_Optional_construct_base<_Ty>, _Ty>;
public:
	static_assert(!is_reference_v<_Ty>,
		"T in optional<T> cannot be a reference type (N4659 23.6.2 [optional.syn]/1).");
	static_assert(!is_same_v<remove_cv_t<_Ty>, nullopt_t>,
		"T in optional<T> cannot be nullopt_t (N4659 23.6.2 [optional.syn]/1).");
	static_assert(!is_same_v<remove_cv_t<_Ty>, in_place_t>,
		"T in optional<T> cannot be in_place_t (N4659 23.6.2 [optional.syn]/1).");
	static_assert(is_reference_v<_Ty> || is_object_v<_Ty>,
		"T in optional<T> must be an object type (N4659 23.6.3 [optional.optional]/3).");
	static_assert(is_destructible_v<_Ty> && !is_array_v<_Ty>,
		"T in optional<T> must satisfy the requirements of Destructible (N4659 23.6.3 [optional.optional]/3).");

	using value_type = _Ty;

	// constructors [optional.object.ctor]
	constexpr optional() noexcept
		: _Mybase{}
		{	// initialize to empty state
		}
	constexpr optional(nullopt_t) noexcept
		: _Mybase{}
		{	// initialize to empty state
		}

	template<class... _Types,
		class = enable_if_t<is_constructible_v<_Ty, _Types...>>>
		constexpr explicit optional(in_place_t, _Types&&... _Args)
		: _Mybase(in_place, _STD forward<_Types>(_Args)...)
		{	// initialize contained value from _Args...
		}

	template<class _Elem,
		class... _Types,
		class = enable_if_t<is_constructible_v<_Ty, initializer_list<_Elem>&, _Types...>>>
		constexpr explicit optional(in_place_t, initializer_list<_Elem> _Ilist, _Types&&... _Args)
		: _Mybase(in_place, _Ilist, _STD forward<_Types>(_Args)...)
		{	// initialize contained value from _Ilist and _Args...
		}

	template<class _Ty2>
		using _AllowDirectConversion = bool_constant<conjunction_v<
			negation<is_same<remove_cv_t<remove_reference_t<_Ty2>>, optional>>,
			negation<is_same<remove_cv_t<remove_reference_t<_Ty2>>, in_place_t>>,
			is_constructible<_Ty, _Ty2>>>;
	template<class _Ty2 = _Ty,
		enable_if_t<conjunction_v<_AllowDirectConversion<_Ty2>,
			is_convertible<_Ty2, _Ty>>, int> = 0>
		constexpr optional(_Ty2&& _Right)
		: _Mybase(in_place, _STD forward<_Ty2>(_Right))
		{	// initialize contained value from _Right
		}
	template<class _Ty2 = _Ty,
		enable_if_t<conjunction_v<_AllowDirectConversion<_Ty2>,
			negation<is_convertible<_Ty2, _Ty>>>, int> = 0>
		constexpr explicit optional(_Ty2&& _Right)
		: _Mybase(in_place, _STD forward<_Ty2>(_Right))
		{	// initialize contained value from _Right
		}

	template<class _Ty2>
		struct _AllowUnwrapping
			: bool_constant<!disjunction_v<
				is_same<_Ty, _Ty2>,
				is_constructible<_Ty, optional<_Ty2>&>,
				is_constructible<_Ty, const optional<_Ty2>&>,
				is_constructible<_Ty, const optional<_Ty2>>,
				is_constructible<_Ty, optional<_Ty2>>,
				is_convertible<optional<_Ty2>&, _Ty>,
				is_convertible<const optional<_Ty2>&, _Ty>,
				is_convertible<const optional<_Ty2>, _Ty>,
				is_convertible<optional<_Ty2>, _Ty>>>
			{};

	template<class _Ty2,
		enable_if_t<conjunction_v<
			_AllowUnwrapping<_Ty2>,
			is_constructible<_Ty, const _Ty2&>,
			is_convertible<const _Ty2&, _Ty>>, int> = 0>
		optional(const optional<_Ty2>& _Right)
		{	// possibly initialize contained value from _Right
		if (_Right)
			{
			this->_Construct(*_Right);
			}
		}
	template<class _Ty2,
		enable_if_t<conjunction_v<
			_AllowUnwrapping<_Ty2>,
			is_constructible<_Ty, const _Ty2&>,
			negation<is_convertible<const _Ty2&, _Ty>>>, int> = 0>
		explicit optional(const optional<_Ty2>& _Right)
		{	// possibly initialize contained value from _Right
		if (_Right)
			{
			this->_Construct(*_Right);
			}
		}

	template<class _Ty2,
		enable_if_t<conjunction_v<
			_AllowUnwrapping<_Ty2>,
			is_constructible<_Ty, _Ty2>,
			is_convertible<_Ty2, _Ty>>, int> = 0>
		optional(optional<_Ty2>&& _Right)
		{	// possibly initialize contained value from _Right
		if (_Right)
			{
			this->_Construct(_STD move(*_Right));
			}
		}
	template<class _Ty2,
		enable_if_t<conjunction_v<
			_AllowUnwrapping<_Ty2>,
			is_constructible<_Ty, _Ty2>,
			negation<is_convertible<_Ty2, _Ty>>>, int> = 0>
		explicit optional(optional<_Ty2>&& _Right)
		{	// possibly initialize contained value from _Right
		if (_Right)
			{
			this->_Construct(_STD move(*_Right));
			}
		}

	// assignment [optional.object.assign]
	optional& operator=(nullopt_t) noexcept
		{	// destroy any contained value and transition to empty state
		reset();
		return (*this);
		}

	template<class _Ty2 = _Ty,
		class = enable_if_t<conjunction_v<
			negation<is_same<optional, remove_cv_t<remove_reference_t<_Ty2>>>>,
			negation<conjunction<is_scalar<_Ty>, is_same<_Ty, decay_t<_Ty2>>>>,
			is_constructible<_Ty, _Ty2>,
			is_assignable<_Ty&, _Ty2>>>>
		optional& operator=(_Ty2&& _Right)
		{	// assign/initialize contained value from _Right
		this->_Assign(_STD forward<_Ty2>(_Right));
		return (*this);
		}

	template<class _Ty2>
		struct _AllowUnwrappingAssignment
			: bool_constant<!disjunction_v<
				is_same<_Ty, _Ty2>,
				is_assignable<_Ty&, optional<_Ty2>&>,
				is_assignable<_Ty&, const optional<_Ty2>&>,
				is_assignable<_Ty&, const optional<_Ty2>>,
				is_assignable<_Ty&, optional<_Ty2>>>>
			{};

	template<class _Ty2,
		class = enable_if_t<conjunction_v<
			_AllowUnwrappingAssignment<_Ty2>,
			is_constructible<_Ty, const _Ty2&>,
			is_assignable<_Ty&, const _Ty2&>>>>
		optional& operator=(const optional<_Ty2>& _Right)
		{	// assign/initialize/destroy contained value from _Right
		if (_Right)
			{
			this->_Assign(*_Right);
			}
		else
			{
			reset();
			}

		return (*this);
		}

	template<class _Ty2,
		class = enable_if_t<conjunction_v<
			_AllowUnwrappingAssignment<_Ty2>,
			is_constructible<_Ty, _Ty2>,
			is_assignable<_Ty&, _Ty2>>>>
		optional& operator=(optional<_Ty2>&& _Right)
		{	// assign/initialize/destroy contained value from _Right
		if (_Right)
			{
			this->_Assign(_STD move(*_Right));
			}
		else
			{
			reset();
			}

		return (*this);
		}

	template<class... _Types>
		_Ty& emplace(_Types&&... _Args)
		{	// destroy any contained value, then initialize from _Args...
		reset();
		return (this->_Construct(_STD forward<_Types>(_Args)...));
		}

	template<class _Elem,
		class... _Types,
		class = enable_if_t<is_constructible_v<_Ty, initializer_list<_Elem>&, _Types...>>>
		_Ty& emplace(initializer_list<_Elem> _Ilist, _Types&&... _Args)
		{	// destroy any contained value, then initialize from _Ilist and _Args...
		reset();
		return (this->_Construct(_Ilist, _STD forward<_Types>(_Args)...));
		}

	// swap [optional.object.swap]
	void swap(optional& _Right)
		_NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty> && is_nothrow_swappable_v<_Ty>)
		{	// exchange state with _Right
		static_assert(is_move_constructible_v<_Ty>,
			"optional<T>::swap requires T to be move constructible (N4659 23.6.3.4 [optional.swap]/1).");
		static_assert(!is_move_constructible_v<_Ty> || is_swappable_v<_Ty>,
			"optional<T>::swap requires T to be swappable (N4659 23.6.3.4 [optional.swap]/1).");
		_Swap(_Right, _Is_trivially_swappable<_Ty>{});
		}

	// observers [optional.object.observe]
	_NODISCARD constexpr const _Ty * operator->() const
		{	// return pointer to contained value
		return (_STD addressof(this->_Get()));
		}
	_NODISCARD constexpr _Ty * operator->()
		{	// return pointer to contained value
		return (_STD addressof(this->_Get()));
		}

	_NODISCARD constexpr const _Ty& operator*() const &
		{	// return reference to contained value
		return (this->_Get());
		}
	_NODISCARD constexpr _Ty& operator*() &
		{	// return reference to contained value
		return (this->_Get());
		}
	_NODISCARD constexpr _Ty&& operator*() &&
		{	// return reference to contained value
		return (_STD move(this->_Get()));
		}
	_NODISCARD constexpr const _Ty&& operator*() const &&
		{	// return reference to contained value
		return (_STD move(this->_Get()));
		}

	constexpr explicit operator bool() const noexcept
		{	// return true iff *this contains a value
		return (this->_Has_value);
		}
	_NODISCARD constexpr bool has_value() const noexcept
		{	// return true iff *this contains a value
		return (this->_Has_value);
		}

	_NODISCARD constexpr const _Ty& value() const &
		{	// return reference to contained value or throw if none
		if (!has_value())
			{
			_THROW(bad_optional_access{});
			}

		return (this->_Get());
		}
	_NODISCARD constexpr _Ty& value() &
		{	// return reference to contained value or throw if none
		if (!has_value())
			{
			_THROW(bad_optional_access{});
			}

		return (this->_Get());
		}
	_NODISCARD constexpr _Ty&& value() &&
		{	// return reference to contained value or throw if none
		if (!has_value())
			{
			_THROW(bad_optional_access{});
			}

		return (_STD move(this->_Get()));
		}
	_NODISCARD constexpr const _Ty&& value() const &&
		{	// return reference to contained value or throw if none
		if (!has_value())
			{
			_THROW(bad_optional_access{});
			}

		return (_STD move(this->_Get()));
		}

	template<class _Ty2>
		_NODISCARD constexpr _Ty value_or(_Ty2&& _Right) const &
		{	// return contained value or _Right if none
		static_assert(is_copy_constructible_v<_Ty>,
			"The const overload of optional<T>::value_or requires T to be copy constructible "
			"(N4659 23.6.3.5 [optional.observe]/18).");
		static_assert(is_convertible_v<_Ty2, _Ty>,
			"optional<T>::value_or(U) requires U to be convertible to T (N4659 23.6.3.5 [optional.observe]/18).");

		if (has_value())
			{
			return (this->_Get());
			}

		return (static_cast<_Ty>(_STD forward<_Ty2>(_Right)));
		}
	template<class _Ty2>
		_NODISCARD constexpr _Ty value_or(_Ty2&& _Right) &&
		{	// return contained value or _Right if none
		static_assert(is_move_constructible_v<_Ty>,
			"The rvalue overload of optional<T>::value_or requires T to be move constructible "
			"(N4659 23.6.3.5 [optional.observe]/20).");
		static_assert(is_convertible_v<_Ty2, _Ty>,
			"optional<T>::value_or(U) requires U to be convertible to T (N4659 23.6.3.5 [optional.observe]/20).");

		if (has_value())
			{
			return (_STD move(this->_Get()));
			}

		return (static_cast<_Ty>(_STD forward<_Ty2>(_Right)));
		}

	// modifiers [optional.object.mod]
	using _Mybase::reset;

private:
	void _Swap(optional& _Right, true_type)
		{	// implement trivial swap
		using _TrivialBaseTy = _Optional_destruct_base<_Ty>;
		_STD swap(static_cast<_TrivialBaseTy&>(*this), static_cast<_TrivialBaseTy&>(_Right));
		}

	void _Swap(optional& _Right, false_type)
		{	// implement non-trivial swap
		const bool _Engaged = has_value();
		if (_Engaged == _Right.has_value())
			{
			if (_Engaged)
				{
				_Swap_adl(**this, *_Right);
				}
			}
		else
			{
			optional& _Source = _Engaged ? *this : _Right;
			optional& _Target = _Engaged ? _Right : *this;
			_Target._Construct(_STD move(*_Source));
			_Source.reset();
			}
		}
	};

template<class _Ty>
	optional(_Ty) -> optional<_Ty>;

		// RELATIONAL OPERATORS [optional.relops]
template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator==(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	const bool _Left_has_value = _Left.has_value();
	return (_Left_has_value == _Right.has_value() && (!_Left_has_value || *_Left == *_Right));
	}

template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator!=(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	const bool _Left_has_value = _Left.has_value();
	return (_Left_has_value != _Right.has_value() || (_Left_has_value && *_Left != *_Right));
	}

template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator<(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right.has_value() && (!_Left.has_value() || *_Left < *_Right));
	}

template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator>(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	return (_Left.has_value() && (!_Right.has_value() || *_Left > *_Right));
	}

template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator<=(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	return (!_Left.has_value() || (_Right.has_value() && *_Left <= *_Right));
	}

template<class _Ty1,
	class _Ty2>
	_NODISCARD constexpr bool operator>=(const optional<_Ty1>& _Left, const optional<_Ty2>& _Right)
	{
	return (!_Right.has_value() || (_Left.has_value() && *_Left >= *_Right));
	}

		// COMPARISONS WITH nullopt [optional.nullops]
template<class _Ty>
	_NODISCARD constexpr bool operator==(const optional<_Ty>& _Left, nullopt_t) noexcept
	{
	return (!_Left.has_value());
	}
template<class _Ty>
	_NODISCARD constexpr bool operator==(nullopt_t, const optional<_Ty>& _Right) noexcept
	{
	return (!_Right.has_value());
	}

template<class _Ty>
	_NODISCARD constexpr bool operator!=(const optional<_Ty>& _Left, nullopt_t) noexcept
	{
	return (_Left.has_value());
	}
template<class _Ty>
	_NODISCARD constexpr bool operator!=(nullopt_t, const optional<_Ty>& _Right) noexcept
	{
	return (_Right.has_value());
	}

template<class _Ty>
	_NODISCARD constexpr bool operator<(const optional<_Ty>&, nullopt_t) noexcept
	{
	return (false);
	}
template<class _Ty>
	_NODISCARD constexpr bool operator<(nullopt_t, const optional<_Ty>& _Right) noexcept
	{
	return (_Right.has_value());
	}

template<class _Ty>
	_NODISCARD constexpr bool operator<=(const optional<_Ty>& _Left, nullopt_t) noexcept
	{
	return (!_Left.has_value());
	}
template<class _Ty>
	_NODISCARD constexpr bool operator<=(nullopt_t, const optional<_Ty>&) noexcept
	{
	return (true);
	}

template<class _Ty>
	_NODISCARD constexpr bool operator>(const optional<_Ty>& _Left, nullopt_t) noexcept
	{
	return (_Left.has_value());
	}
template<class _Ty>
	_NODISCARD constexpr bool operator>(nullopt_t, const optional<_Ty>&) noexcept
	{
	return (false);
	}

template<class _Ty>
	_NODISCARD constexpr bool operator>=(const optional<_Ty>&, nullopt_t) noexcept
	{
	return (true);
	}
template<class _Ty>
	_NODISCARD constexpr bool operator>=(nullopt_t, const optional<_Ty>& _Right) noexcept
	{
	return (!_Right.has_value());
	}

		// COMPARISONS WITH T [optional.comp_with_t]
template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_equal
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_equal<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() == _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() == _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_not_equal
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_not_equal<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() != _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() != _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_less
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_less<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() < _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() < _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_less_equal
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_less_equal<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() <= _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() <= _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_greater
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_greater<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() > _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() > _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Lhs,
	class _Rhs,
	class = void>
	struct _Are_comparable_with_greater_equal
		: false_type
	{
	};

template<class _Lhs,
	class _Rhs>
	struct _Are_comparable_with_greater_equal<_Lhs, _Rhs, void_t<
		decltype(_STD declval<const _Lhs&>() >= _STD declval<const _Rhs&>())>>
		: is_convertible<decltype(_STD declval<const _Lhs&>() >= _STD declval<const _Rhs&>()), bool>::type
	{
	};

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator==(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left == _Right : false);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator==(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left == *_Right : false);
	}

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_not_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator!=(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left != _Right : true);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_not_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator!=(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left != *_Right : true);
	}

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_less<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator<(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left < _Right : true);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_less<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator<(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left < *_Right : false);
	}

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_less_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator<=(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left <= _Right : true);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_less_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator<=(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left <= *_Right : false);
	}

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_greater<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator>(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left > _Right : false);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_greater<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator>(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left > *_Right : true);
	}

template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_greater_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator>=(const optional<_Ty1>& _Left, const _Ty2& _Right)
	{
	return (_Left ? *_Left >= _Right : false);
	}
template<class _Ty1,
	class _Ty2,
	enable_if_t<_Are_comparable_with_greater_equal<_Ty1, _Ty2>::value, int> = 0>
	_NODISCARD constexpr bool operator>=(const _Ty1& _Left, const optional<_Ty2>& _Right)
	{
	return (_Right ? _Left >= *_Right : true);
	}

		// FUNCTION TEMPLATE swap [optional.specalg]
template<class _Ty,
	class = enable_if_t<is_move_constructible_v<_Ty> && is_swappable_v<_Ty>>> inline
	void swap(optional<_Ty>& _Left, optional<_Ty>& _Right)
		_NOEXCEPT_COND(_NOEXCEPT_OPER(_Left.swap(_Right)))
	{	// exchange the values of _Left and _Right
	_Left.swap(_Right);
	}

		// FUNCTION TEMPLATE make_optional [optional.specalg]
template<class _Ty>
	_NODISCARD constexpr optional<decay_t<_Ty>> make_optional(_Ty&& _Value)
	{	// Construct an optional from _Value
	return (optional<decay_t<_Ty>>{_STD forward<_Ty>(_Value)});
	}
template<class _Ty,
	class... _Types>
	_NODISCARD constexpr optional<_Ty> make_optional(_Types&&... _Args)
	{	// Construct an optional from _Args
	return (optional<_Ty>{in_place, _STD forward<_Types>(_Args)...});
	}
template<class _Ty,
	class _Elem,
	class... _Types>
	_NODISCARD constexpr optional<_Ty> make_optional(initializer_list<_Elem> _Ilist, _Types&&... _Args)
	{	// Construct an optional from _Ilist and _Args
	return (optional<_Ty>{in_place, _Ilist, _STD forward<_Types>(_Args)...});
	}

		// STRUCT TEMPLATE SPECIALIZATION hash [optional.hash]
template<class _Ty>
	struct hash<optional<_Ty>>
		: _Conditionally_enabled_hash<optional<_Ty>,
			is_default_constructible_v<hash<remove_const_t<_Ty>>>>
	{	// hash functor for optional<_Ty>
	static size_t _Do_hash(const optional<_Ty>& _Opt)
			_NOEXCEPT_COND(_Is_nothrow_hashable<remove_const_t<_Ty>>::value) // strengthened
		{
		constexpr size_t _Unspecified_value = 0;

		if (_Opt)
			{
			return (hash<remove_const_t<_Ty>>{}(*_Opt));
			}

		return (_Unspecified_value);
		}
	};

_STD_END

 #pragma pop_macro("new")
 _STL_RESTORE_CLANG_WARNINGS
 #pragma warning(pop)
 #pragma pack(pop)
#else /* ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv */
 #pragma message("class template optional is only available with C++17 or later.")
#endif /* _HAS_CXX17 */
#endif /* RC_INVOKED */
#endif /* _OPTIONAL_ */
