cosmopolitan/third_party/libcxx/optional
Justine Tunney cf93ecbbb2 Prove that Makefile is fully defined
The whole repository is now buildable with GNU Make Landlock sandboxing.
This proves that no Makefile targets exist which touch files other than
their declared prerequisites. In order to do this, we had to:

  1. Stop code morphing GCC output in package.com and instead run a
     newly introduced FIXUPOBJ.COM command after GCC invocations.

  2. Disable all the crumby Python unit tests that do things like create
     files in the current directory, or rename() files between folders.
     This ended up being a lot of tests, but most of them are still ok.

  3. Introduce an .UNSANDBOXED variable to GNU Make to disable Landlock.
     We currently only do this for things like `make tags`.

  4. This change deletes some GNU Make code that was preventing the
     execve() optimization from working. This means it should no longer
     be necessary in most cases for command invocations to be indirected
     through the cocmd interpreter.

  5. Missing dependencies had to be declared in certain places, in cases
     where they couldn't be automatically determined by MKDEPS.COM

  6. The libcxx header situation has finally been tamed. One of the
     things that makes this difficult is MKDEPS.COM only wants to
     consider the first 64kb of a file, in order to go fast. But libcxx
     likes to have #include lines buried after huge documentation.

  7. An .UNVEIL variable has been introduced to GNU Make just in case
     we ever wish to explicitly specify additional things that need to
     be whitelisted which aren't strictly prerequisites. This works in
     a manner similar to the recently introduced .EXTRA_PREREQS feature.

There's now a new build/bootstrap/make.com prebuilt binary available. It
should no longer be possible to write invalid Makefile code.
2022-08-06 04:05:08 -07:00

1420 lines
42 KiB
C++

// -*- C++ -*-
//===-------------------------- optional ----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_OPTIONAL
#define _LIBCPP_OPTIONAL
#include "third_party/libcxx/__config"
#include "third_party/libcxx/__debug"
#include "third_party/libcxx/__functional_base"
#include "third_party/libcxx/functional"
#include "third_party/libcxx/initializer_list"
#include "third_party/libcxx/new"
#include "third_party/libcxx/stdexcept"
#include "third_party/libcxx/type_traits"
#include "third_party/libcxx/utility"
#include "third_party/libcxx/version"
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include "third_party/libcxx/__undef_macros"
/*
optional synopsis
// C++1z
namespace std {
// 23.6.3, optional for object types
template <class T> class optional;
// 23.6.4, no-value state indicator
struct nullopt_t{see below };
inline constexpr nullopt_t nullopt(unspecified );
// 23.6.5, class bad_optional_access
class bad_optional_access;
// 23.6.6, relational operators
template <class T, class U>
constexpr bool operator==(const optional<T>&, const optional<U>&);
template <class T, class U>
constexpr bool operator!=(const optional<T>&, const optional<U>&);
template <class T, class U>
constexpr bool operator<(const optional<T>&, const optional<U>&);
template <class T, class U>
constexpr bool operator>(const optional<T>&, const optional<U>&);
template <class T, class U>
constexpr bool operator<=(const optional<T>&, const optional<U>&);
template <class T, class U>
constexpr bool operator>=(const optional<T>&, const optional<U>&);
// 23.6.7 comparison with nullopt
template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
// 23.6.8, comparison with T
template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
// 23.6.9, specialized algorithms
template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
template <class T> constexpr optional<see below > make_optional(T&&);
template <class T, class... Args>
constexpr optional<T> make_optional(Args&&... args);
template <class T, class U, class... Args>
constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
// 23.6.10, hash support
template <class T> struct hash;
template <class T> struct hash<optional<T>>;
template <class T> class optional {
public:
using value_type = T;
// 23.6.3.1, constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
optional(const optional &);
optional(optional &&) noexcept(see below);
template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
template <class U = T>
constexpr EXPLICIT optional(U &&);
template <class U>
constexpr EXPLICIT optional(const optional<U> &);
template <class U>
constexpr EXPLICIT optional(optional<U> &&);
// 23.6.3.2, destructor
~optional();
// 23.6.3.3, assignment
optional &operator=(nullopt_t) noexcept;
optional &operator=(const optional &); // constexpr in C++20
optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
template <class U = T> optional &operator=(U &&);
template <class U> optional &operator=(const optional<U> &);
template <class U> optional &operator=(optional<U> &&);
template <class... Args> T& emplace(Args &&...);
template <class U, class... Args>
T& emplace(initializer_list<U>, Args &&...);
// 23.6.3.4, swap
void swap(optional &) noexcept(see below );
// 23.6.3.5, observers
constexpr T const *operator->() const;
constexpr T *operator->();
constexpr T const &operator*() const &;
constexpr T &operator*() &;
constexpr T &&operator*() &&;
constexpr const T &&operator*() const &&;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr T const &value() const &;
constexpr T &value() &;
constexpr T &&value() &&;
constexpr const T &&value() const &&;
template <class U> constexpr T value_or(U &&) const &;
template <class U> constexpr T value_or(U &&) &&;
// 23.6.3.6, modifiers
void reset() noexcept;
private:
T *val; // exposition only
};
template<class T>
optional(T) -> optional<T>;
} // namespace std
*/
namespace std // purposefully not using versioning namespace
{
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
: public exception
{
public:
// Get the key function ~bad_optional_access() into the dylib
virtual ~bad_optional_access() _NOEXCEPT;
virtual const char* what() const _NOEXCEPT;
};
} // std
#if _LIBCPP_STD_VER > 14
_LIBCPP_BEGIN_NAMESPACE_STD
_LIBCPP_NORETURN
inline _LIBCPP_INLINE_VISIBILITY
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
void __throw_bad_optional_access() {
#ifndef _LIBCPP_NO_EXCEPTIONS
throw bad_optional_access();
#else
_VSTD::abort();
#endif
}
struct nullopt_t
{
struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
_LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
};
_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
struct __optional_destruct_base;
template <class _Tp>
struct __optional_destruct_base<_Tp, false>
{
typedef _Tp value_type;
static_assert(is_object_v<value_type>,
"instantiation of optional with a non-object type is undefined behavior");
union
{
char __null_state_;
value_type __val_;
};
bool __engaged_;
_LIBCPP_INLINE_VISIBILITY
~__optional_destruct_base()
{
if (__engaged_)
__val_.~value_type();
}
_LIBCPP_INLINE_VISIBILITY
constexpr __optional_destruct_base() noexcept
: __null_state_(),
__engaged_(false) {}
template <class... _Args>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
: __val_(_VSTD::forward<_Args>(__args)...),
__engaged_(true) {}
_LIBCPP_INLINE_VISIBILITY
void reset() noexcept
{
if (__engaged_)
{
__val_.~value_type();
__engaged_ = false;
}
}
};
template <class _Tp>
struct __optional_destruct_base<_Tp, true>
{
typedef _Tp value_type;
static_assert(is_object_v<value_type>,
"instantiation of optional with a non-object type is undefined behavior");
union
{
char __null_state_;
value_type __val_;
};
bool __engaged_;
_LIBCPP_INLINE_VISIBILITY
constexpr __optional_destruct_base() noexcept
: __null_state_(),
__engaged_(false) {}
template <class... _Args>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
: __val_(_VSTD::forward<_Args>(__args)...),
__engaged_(true) {}
_LIBCPP_INLINE_VISIBILITY
void reset() noexcept
{
if (__engaged_)
{
__engaged_ = false;
}
}
};
template <class _Tp, bool = is_reference<_Tp>::value>
struct __optional_storage_base : __optional_destruct_base<_Tp>
{
using __base = __optional_destruct_base<_Tp>;
using value_type = _Tp;
using __base::__base;
_LIBCPP_INLINE_VISIBILITY
constexpr bool has_value() const noexcept
{
return this->__engaged_;
}
_LIBCPP_INLINE_VISIBILITY
constexpr value_type& __get() & noexcept
{
return this->__val_;
}
_LIBCPP_INLINE_VISIBILITY
constexpr const value_type& __get() const& noexcept
{
return this->__val_;
}
_LIBCPP_INLINE_VISIBILITY
constexpr value_type&& __get() && noexcept
{
return _VSTD::move(this->__val_);
}
_LIBCPP_INLINE_VISIBILITY
constexpr const value_type&& __get() const&& noexcept
{
return _VSTD::move(this->__val_);
}
template <class... _Args>
_LIBCPP_INLINE_VISIBILITY
void __construct(_Args&&... __args)
{
_LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
this->__engaged_ = true;
}
template <class _That>
_LIBCPP_INLINE_VISIBILITY
void __construct_from(_That&& __opt)
{
if (__opt.has_value())
__construct(_VSTD::forward<_That>(__opt).__get());
}
template <class _That>
_LIBCPP_INLINE_VISIBILITY
void __assign_from(_That&& __opt)
{
if (this->__engaged_ == __opt.has_value())
{
if (this->__engaged_)
this->__val_ = _VSTD::forward<_That>(__opt).__get();
}
else
{
if (this->__engaged_)
this->reset();
else
__construct(_VSTD::forward<_That>(__opt).__get());
}
}
};
// optional<T&> is currently required ill-formed, however it may to be in the
// future. For this reason it has already been implemented to ensure we can
// make the change in an ABI compatible manner.
template <class _Tp>
struct __optional_storage_base<_Tp, true>
{
using value_type = _Tp;
using __raw_type = remove_reference_t<_Tp>;
__raw_type* __value_;
template <class _Up>
static constexpr bool __can_bind_reference() {
using _RawUp = typename remove_reference<_Up>::type;
using _UpPtr = _RawUp*;
using _RawTp = typename remove_reference<_Tp>::type;
using _TpPtr = _RawTp*;
using _CheckLValueArg = integral_constant<bool,
(is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
|| is_same<_RawUp, reference_wrapper<_RawTp>>::value
|| is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
>;
return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
|| (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
is_convertible<_UpPtr, _TpPtr>::value);
}
_LIBCPP_INLINE_VISIBILITY
constexpr __optional_storage_base() noexcept
: __value_(nullptr) {}
template <class _UArg>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
: __value_(_VSTD::addressof(__uarg))
{
static_assert(__can_bind_reference<_UArg>(),
"Attempted to construct a reference element in tuple from a "
"possible temporary");
}
_LIBCPP_INLINE_VISIBILITY
void reset() noexcept { __value_ = nullptr; }
_LIBCPP_INLINE_VISIBILITY
constexpr bool has_value() const noexcept
{ return __value_ != nullptr; }
_LIBCPP_INLINE_VISIBILITY
constexpr value_type& __get() const& noexcept
{ return *__value_; }
_LIBCPP_INLINE_VISIBILITY
constexpr value_type&& __get() const&& noexcept
{ return _VSTD::forward<value_type>(*__value_); }
template <class _UArg>
_LIBCPP_INLINE_VISIBILITY
void __construct(_UArg&& __val)
{
_LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
static_assert(__can_bind_reference<_UArg>(),
"Attempted to construct a reference element in tuple from a "
"possible temporary");
__value_ = _VSTD::addressof(__val);
}
template <class _That>
_LIBCPP_INLINE_VISIBILITY
void __construct_from(_That&& __opt)
{
if (__opt.has_value())
__construct(_VSTD::forward<_That>(__opt).__get());
}
template <class _That>
_LIBCPP_INLINE_VISIBILITY
void __assign_from(_That&& __opt)
{
if (has_value() == __opt.has_value())
{
if (has_value())
*__value_ = _VSTD::forward<_That>(__opt).__get();
}
else
{
if (has_value())
reset();
else
__construct(_VSTD::forward<_That>(__opt).__get());
}
}
};
template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
struct __optional_copy_base : __optional_storage_base<_Tp>
{
using __optional_storage_base<_Tp>::__optional_storage_base;
};
template <class _Tp>
struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
{
using __optional_storage_base<_Tp>::__optional_storage_base;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base(const __optional_copy_base& __opt)
{
this->__construct_from(__opt);
}
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base(__optional_copy_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base& operator=(const __optional_copy_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_base& operator=(__optional_copy_base&&) = default;
};
template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
struct __optional_move_base : __optional_copy_base<_Tp>
{
using __optional_copy_base<_Tp>::__optional_copy_base;
};
template <class _Tp>
struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
{
using value_type = _Tp;
using __optional_copy_base<_Tp>::__optional_copy_base;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base(const __optional_move_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base(__optional_move_base&& __opt)
noexcept(is_nothrow_move_constructible_v<value_type>)
{
this->__construct_from(_VSTD::move(__opt));
}
_LIBCPP_INLINE_VISIBILITY
__optional_move_base& operator=(const __optional_move_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_base& operator=(__optional_move_base&&) = default;
};
template <class _Tp, bool =
is_trivially_destructible<_Tp>::value &&
is_trivially_copy_constructible<_Tp>::value &&
is_trivially_copy_assignable<_Tp>::value>
struct __optional_copy_assign_base : __optional_move_base<_Tp>
{
using __optional_move_base<_Tp>::__optional_move_base;
};
template <class _Tp>
struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
{
using __optional_move_base<_Tp>::__optional_move_base;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base(const __optional_copy_assign_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base(__optional_copy_assign_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
{
this->__assign_from(__opt);
return *this;
}
_LIBCPP_INLINE_VISIBILITY
__optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
};
template <class _Tp, bool =
is_trivially_destructible<_Tp>::value &&
is_trivially_move_constructible<_Tp>::value &&
is_trivially_move_assignable<_Tp>::value>
struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
{
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
};
template <class _Tp>
struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
{
using value_type = _Tp;
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base() = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base(__optional_move_assign_base&&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
_LIBCPP_INLINE_VISIBILITY
__optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
noexcept(is_nothrow_move_assignable_v<value_type> &&
is_nothrow_move_constructible_v<value_type>)
{
this->__assign_from(_VSTD::move(__opt));
return *this;
}
};
template <class _Tp>
using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
is_copy_constructible<_Tp>::value,
is_move_constructible<_Tp>::value
>;
template <class _Tp>
using __optional_sfinae_assign_base_t = __sfinae_assign_base<
(is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
(is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
>;
template <class _Tp>
class optional
: private __optional_move_assign_base<_Tp>
, private __optional_sfinae_ctor_base_t<_Tp>
, private __optional_sfinae_assign_base_t<_Tp>
{
using __base = __optional_move_assign_base<_Tp>;
public:
using value_type = _Tp;
private:
// Disable the reference extension using this static assert.
static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
"instantiation of optional with in_place_t is ill-formed");
static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
"instantiation of optional with nullopt_t is ill-formed");
static_assert(!is_reference_v<value_type>,
"instantiation of optional with a reference type is ill-formed");
static_assert(is_destructible_v<value_type>,
"instantiation of optional with a non-destructible type is ill-formed");
static_assert(!is_array_v<value_type>,
"instantiation of optional with an array type is ill-formed");
// LWG2756: conditionally explicit conversion from _Up
struct _CheckOptionalArgsConstructor {
template <class _Up>
static constexpr bool __enable_implicit() {
return is_constructible_v<_Tp, _Up&&> &&
is_convertible_v<_Up&&, _Tp>;
}
template <class _Up>
static constexpr bool __enable_explicit() {
return is_constructible_v<_Tp, _Up&&> &&
!is_convertible_v<_Up&&, _Tp>;
}
};
template <class _Up>
using _CheckOptionalArgsCtor = _If<
_IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
_IsNotSame<__uncvref_t<_Up>, optional>::value,
_CheckOptionalArgsConstructor,
__check_tuple_constructor_fail
>;
template <class _QualUp>
struct _CheckOptionalLikeConstructor {
template <class _Up, class _Opt = optional<_Up>>
using __check_constructible_from_opt = _Or<
is_constructible<_Tp, _Opt&>,
is_constructible<_Tp, _Opt const&>,
is_constructible<_Tp, _Opt&&>,
is_constructible<_Tp, _Opt const&&>,
is_convertible<_Opt&, _Tp>,
is_convertible<_Opt const&, _Tp>,
is_convertible<_Opt&&, _Tp>,
is_convertible<_Opt const&&, _Tp>
>;
template <class _Up, class _Opt = optional<_Up>>
using __check_assignable_from_opt = _Or<
is_assignable<_Tp&, _Opt&>,
is_assignable<_Tp&, _Opt const&>,
is_assignable<_Tp&, _Opt&&>,
is_assignable<_Tp&, _Opt const&&>
>;
template <class _Up, class _QUp = _QualUp>
static constexpr bool __enable_implicit() {
return is_convertible<_QUp, _Tp>::value &&
!__check_constructible_from_opt<_Up>::value;
}
template <class _Up, class _QUp = _QualUp>
static constexpr bool __enable_explicit() {
return !is_convertible<_QUp, _Tp>::value &&
!__check_constructible_from_opt<_Up>::value;
}
template <class _Up, class _QUp = _QualUp>
static constexpr bool __enable_assign() {
// Construction and assignability of _Qup to _Tp has already been
// checked.
return !__check_constructible_from_opt<_Up>::value &&
!__check_assignable_from_opt<_Up>::value;
}
};
template <class _Up, class _QualUp>
using _CheckOptionalLikeCtor = _If<
_And<
_IsNotSame<_Up, _Tp>,
is_constructible<_Tp, _QualUp>
>::value,
_CheckOptionalLikeConstructor<_QualUp>,
__check_tuple_constructor_fail
>;
template <class _Up, class _QualUp>
using _CheckOptionalLikeAssign = _If<
_And<
_IsNotSame<_Up, _Tp>,
is_constructible<_Tp, _QualUp>,
is_assignable<_Tp&, _QualUp>
>::value,
_CheckOptionalLikeConstructor<_QualUp>,
__check_tuple_constructor_fail
>;
public:
_LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
_LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
_LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
_LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
template <class _InPlaceT, class... _Args, class = _EnableIf<
_And<
_IsSame<_InPlaceT, in_place_t>,
is_constructible<value_type, _Args...>
>::value
>
>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit optional(_InPlaceT, _Args&&... __args)
: __base(in_place, _VSTD::forward<_Args>(__args)...) {}
template <class _Up, class... _Args, class = _EnableIf<
is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
: __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
template <class _Up = value_type, _EnableIf<
_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
constexpr optional(_Up&& __v)
: __base(in_place, _VSTD::forward<_Up>(__v)) {}
template <class _Up, _EnableIf<
_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
constexpr explicit optional(_Up&& __v)
: __base(in_place, _VSTD::forward<_Up>(__v)) {}
// LWG2756: conditionally explicit conversion from const optional<_Up>&
template <class _Up, _EnableIf<
_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
optional(const optional<_Up>& __v)
{
this->__construct_from(__v);
}
template <class _Up, _EnableIf<
_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
explicit optional(const optional<_Up>& __v)
{
this->__construct_from(__v);
}
// LWG2756: conditionally explicit conversion from optional<_Up>&&
template <class _Up, _EnableIf<
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
optional(optional<_Up>&& __v)
{
this->__construct_from(_VSTD::move(__v));
}
template <class _Up, _EnableIf<
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
explicit optional(optional<_Up>&& __v)
{
this->__construct_from(_VSTD::move(__v));
}
_LIBCPP_INLINE_VISIBILITY
optional& operator=(nullopt_t) noexcept
{
reset();
return *this;
}
_LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
_LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
// LWG2756
template <class _Up = value_type,
class = _EnableIf<
_And<
_IsNotSame<__uncvref_t<_Up>, optional>,
_Or<
_IsNotSame<__uncvref_t<_Up>, value_type>,
_Not<is_scalar<value_type>>
>,
is_constructible<value_type, _Up>,
is_assignable<value_type&, _Up>
>::value>
>
_LIBCPP_INLINE_VISIBILITY
optional&
operator=(_Up&& __v)
{
if (this->has_value())
this->__get() = _VSTD::forward<_Up>(__v);
else
this->__construct(_VSTD::forward<_Up>(__v));
return *this;
}
// LWG2756
template <class _Up, _EnableIf<
_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
optional&
operator=(const optional<_Up>& __v)
{
this->__assign_from(__v);
return *this;
}
// LWG2756
template <class _Up, _EnableIf<
_CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
, int> = 0>
_LIBCPP_INLINE_VISIBILITY
optional&
operator=(optional<_Up>&& __v)
{
this->__assign_from(_VSTD::move(__v));
return *this;
}
template <class... _Args,
class = _EnableIf
<
is_constructible_v<value_type, _Args...>
>
>
_LIBCPP_INLINE_VISIBILITY
_Tp &
emplace(_Args&&... __args)
{
reset();
this->__construct(_VSTD::forward<_Args>(__args)...);
return this->__get();
}
template <class _Up, class... _Args,
class = _EnableIf
<
is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
>
>
_LIBCPP_INLINE_VISIBILITY
_Tp &
emplace(initializer_list<_Up> __il, _Args&&... __args)
{
reset();
this->__construct(__il, _VSTD::forward<_Args>(__args)...);
return this->__get();
}
_LIBCPP_INLINE_VISIBILITY
void swap(optional& __opt)
noexcept(is_nothrow_move_constructible_v<value_type> &&
is_nothrow_swappable_v<value_type>)
{
if (this->has_value() == __opt.has_value())
{
using _VSTD::swap;
if (this->has_value())
swap(this->__get(), __opt.__get());
}
else
{
if (this->has_value())
{
__opt.__construct(_VSTD::move(this->__get()));
reset();
}
else
{
this->__construct(_VSTD::move(__opt.__get()));
__opt.reset();
}
}
}
_LIBCPP_INLINE_VISIBILITY
constexpr
add_pointer_t<value_type const>
operator->() const
{
_LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
return _VSTD::addressof(this->__get());
#else
return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
#endif
}
_LIBCPP_INLINE_VISIBILITY
constexpr
add_pointer_t<value_type>
operator->()
{
_LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
return _VSTD::addressof(this->__get());
#else
return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
#endif
}
_LIBCPP_INLINE_VISIBILITY
constexpr
const value_type&
operator*() const&
{
_LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
return this->__get();
}
_LIBCPP_INLINE_VISIBILITY
constexpr
value_type&
operator*() &
{
_LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
return this->__get();
}
_LIBCPP_INLINE_VISIBILITY
constexpr
value_type&&
operator*() &&
{
_LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
return _VSTD::move(this->__get());
}
_LIBCPP_INLINE_VISIBILITY
constexpr
const value_type&&
operator*() const&&
{
_LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
return _VSTD::move(this->__get());
}
_LIBCPP_INLINE_VISIBILITY
constexpr explicit operator bool() const noexcept { return has_value(); }
using __base::has_value;
using __base::__get;
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
constexpr value_type const& value() const&
{
if (!this->has_value())
__throw_bad_optional_access();
return this->__get();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
constexpr value_type& value() &
{
if (!this->has_value())
__throw_bad_optional_access();
return this->__get();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
constexpr value_type&& value() &&
{
if (!this->has_value())
__throw_bad_optional_access();
return _VSTD::move(this->__get());
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
constexpr value_type const&& value() const&&
{
if (!this->has_value())
__throw_bad_optional_access();
return _VSTD::move(this->__get());
}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
constexpr value_type value_or(_Up&& __v) const&
{
static_assert(is_copy_constructible_v<value_type>,
"optional<T>::value_or: T must be copy constructible");
static_assert(is_convertible_v<_Up, value_type>,
"optional<T>::value_or: U must be convertible to T");
return this->has_value() ? this->__get() :
static_cast<value_type>(_VSTD::forward<_Up>(__v));
}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
constexpr value_type value_or(_Up&& __v) &&
{
static_assert(is_move_constructible_v<value_type>,
"optional<T>::value_or: T must be move constructible");
static_assert(is_convertible_v<_Up, value_type>,
"optional<T>::value_or: U must be convertible to T");
return this->has_value() ? _VSTD::move(this->__get()) :
static_cast<value_type>(_VSTD::forward<_Up>(__v));
}
using __base::reset;
private:
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
static _Up*
__operator_arrow(true_type, _Up& __x)
{
return _VSTD::addressof(__x);
}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY
static constexpr _Up*
__operator_arrow(false_type, _Up& __x)
{
return &__x;
}
};
#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
template<class T>
optional(T) -> optional<T>;
#endif
// Comparisons between optionals
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x == *__y;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
return false;
return *__x != *__y;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x < *__y;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__x))
return false;
if (!static_cast<bool>(__y))
return true;
return *__x > *__y;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__x))
return true;
if (!static_cast<bool>(__y))
return false;
return *__x <= *__y;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
return false;
return *__x >= *__y;
}
// Comparisons with nullopt
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator==(const optional<_Tp>& __x, nullopt_t) noexcept
{
return !static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator==(nullopt_t, const optional<_Tp>& __x) noexcept
{
return !static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator<(const optional<_Tp>&, nullopt_t) noexcept
{
return false;
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator<(nullopt_t, const optional<_Tp>& __x) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
{
return !static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator<=(nullopt_t, const optional<_Tp>&) noexcept
{
return true;
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator>(const optional<_Tp>& __x, nullopt_t) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator>(nullopt_t, const optional<_Tp>&) noexcept
{
return false;
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator>=(const optional<_Tp>&, nullopt_t) noexcept
{
return true;
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
bool
operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
{
return !static_cast<bool>(__x);
}
// Comparisons with T
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x == __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v == *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x != __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v != *__x : true;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x < __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v < *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x <= __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v <= *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x > __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v > *__x : true;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x >= __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
_EnableIf<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v >= *__x : true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_EnableIf<
is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
void
>
swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
{
__x.swap(__y);
}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY constexpr
optional<decay_t<_Tp>> make_optional(_Tp&& __v)
{
return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
}
template <class _Tp, class... _Args>
_LIBCPP_INLINE_VISIBILITY constexpr
optional<_Tp> make_optional(_Args&&... __args)
{
return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
}
template <class _Tp, class _Up, class... _Args>
_LIBCPP_INLINE_VISIBILITY constexpr
optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
{
return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
}
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS hash<
__enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
>
{
typedef optional<_Tp> argument_type;
typedef size_t result_type;
_LIBCPP_INLINE_VISIBILITY
result_type operator()(const argument_type& __opt) const
{
return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
}
};
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER > 14
_LIBCPP_POP_MACROS
#endif // _LIBCPP_OPTIONAL