Certain headers require `optional<T&>`, so it may be beneficial to split out `optional<T>` and `optional<T&>`. This can allow consumers to only bring in the `optional` flavour it needs.. - Parcel out the respective pieces into their own header. - Certain sources rely on transitive includes brought in by `<optional>`, so they're kept there for now, and only tests have been fixed. --------- Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
315 lines
13 KiB
C++
315 lines
13 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
|
|
/*
|
|
optional synopsis
|
|
|
|
// C++1z
|
|
|
|
namespace std {
|
|
// [optional.optional], class template optional
|
|
template <class T>
|
|
class optional;
|
|
|
|
template<class T>
|
|
constexpr bool ranges::enable_view<optional<T>> = true;
|
|
template<class T>
|
|
constexpr auto format_kind<optional<T>> = range_format::disabled;
|
|
|
|
template<class T>
|
|
concept is-derived-from-optional = requires(const T& t) { // exposition only
|
|
[]<class U>(const optional<U>&){ }(t);
|
|
};
|
|
|
|
// [optional.nullopt], no-value state indicator
|
|
struct nullopt_t{see below };
|
|
inline constexpr nullopt_t nullopt(unspecified );
|
|
|
|
// [optional.bad.access], class bad_optional_access
|
|
class bad_optional_access;
|
|
|
|
// [optional.relops], 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>&);
|
|
template<class T, three_way_comparable_with<T> U>
|
|
constexpr compare_three_way_result_t<T, U>
|
|
operator<=>(const optional<T>&, const optional<U>&); // since C++20
|
|
|
|
// [optional.nullops], 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; // until C++17
|
|
template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
|
|
template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
|
|
template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; // until C++17
|
|
template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; // until C++17
|
|
template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
|
|
template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
|
|
template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; // until C++17
|
|
template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; // until C++17
|
|
template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
|
|
template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
|
|
template<class T>
|
|
constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // since C++20
|
|
|
|
// [optional.comp.with.t], 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>&);
|
|
template<class T, class U>
|
|
requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
|
|
constexpr compare_three_way_result_t<T, U>
|
|
operator<=>(const optional<T>&, const U&); // since C++20
|
|
|
|
// [optional.specalg], specialized algorithms
|
|
template<class T>
|
|
void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
|
|
|
|
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);
|
|
|
|
// [optional.hash], hash support
|
|
template<class T> struct hash;
|
|
template<class T> struct hash<optional<T>>;
|
|
|
|
template<class T>
|
|
class optional {
|
|
public:
|
|
using value_type = T;
|
|
using iterator = implementation-defined; // see [optional.iterators]
|
|
using const_iterator = implementation-defined; // see [optional.iterators]
|
|
|
|
// [optional.ctor], constructors
|
|
constexpr optional() noexcept;
|
|
constexpr optional(nullopt_t) noexcept;
|
|
constexpr optional(const optional &);
|
|
constexpr 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 = remove_cv_t<T>>
|
|
constexpr explicit(see-below) optional(U &&);
|
|
template<class U>
|
|
explicit(see-below) optional(const optional<U> &); // constexpr in C++20
|
|
template<class U>
|
|
explicit(see-below) optional(optional<U> &&); // constexpr in C++20
|
|
|
|
// [optional.dtor], destructor
|
|
~optional(); // constexpr in C++20
|
|
|
|
// [optional.assign], assignment
|
|
optional &operator=(nullopt_t) noexcept; // constexpr in C++20
|
|
constexpr optional &operator=(const optional &);
|
|
constexpr optional &operator=(optional &&) noexcept(see below);
|
|
template<class U = remove_cv_t<T>> optional &operator=(U &&); // constexpr in C++20
|
|
template<class U> optional &operator=(const optional<U> &); // constexpr in C++20
|
|
template<class U> optional &operator=(optional<U> &&); // constexpr in C++20
|
|
template<class... Args> T& emplace(Args &&...); // constexpr in C++20
|
|
template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
|
|
|
|
// [optional.swap], swap
|
|
void swap(optional &) noexcept(see below ); // constexpr in C++20
|
|
|
|
// [optional.iterators], iterator support
|
|
constexpr iterator begin() noexcept;
|
|
constexpr const_iterator begin() const noexcept;
|
|
constexpr iterator end() noexcept;
|
|
constexpr const_iterator end() const noexcept;
|
|
|
|
// [optional.observe], observers
|
|
constexpr T const *operator->() const noexcept;
|
|
constexpr T *operator->() noexcept;
|
|
constexpr T const &operator*() const & noexcept;
|
|
constexpr T &operator*() & noexcept;
|
|
constexpr T &&operator*() && noexcept;
|
|
constexpr const T &&operator*() const && noexcept;
|
|
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 = remove_cv_t<T>> constexpr T value_or(U &&) const &;
|
|
template<class U = remove_cv_t<T>> constexpr T value_or(U &&) &&;
|
|
|
|
// [optional.monadic], monadic operations
|
|
template<class F> constexpr auto and_then(F&& f) &; // since C++23
|
|
template<class F> constexpr auto and_then(F&& f) &&; // since C++23
|
|
template<class F> constexpr auto and_then(F&& f) const&; // since C++23
|
|
template<class F> constexpr auto and_then(F&& f) const&&; // since C++23
|
|
template<class F> constexpr auto transform(F&& f) &; // since C++23
|
|
template<class F> constexpr auto transform(F&& f) &&; // since C++23
|
|
template<class F> constexpr auto transform(F&& f) const&; // since C++23
|
|
template<class F> constexpr auto transform(F&& f) const&&; // since C++23
|
|
template<class F> constexpr optional or_else(F&& f) &&; // since C++23
|
|
template<class F> constexpr optional or_else(F&& f) const&; // since C++23
|
|
|
|
// [optional.mod], modifiers
|
|
void reset() noexcept; // constexpr in C++20
|
|
|
|
private:
|
|
T *val; // exposition only
|
|
};
|
|
|
|
template<class T>
|
|
optional(T) -> optional<T>;
|
|
|
|
template<class T>
|
|
class optional<T&> { // since C++26
|
|
public:
|
|
using value_type = T;
|
|
using iterator = implementation-defined; // see [optional.ref.iterators]
|
|
|
|
public:
|
|
// [optional.ref.ctor], constructors
|
|
constexpr optional() noexcept = default;
|
|
constexpr optional(nullopt_t) noexcept : optional() {}
|
|
constexpr optional(const optional& rhs) noexcept = default;
|
|
|
|
template<class Arg>
|
|
constexpr explicit optional(in_place_t, Arg&& arg);
|
|
template<class U>
|
|
constexpr explicit(see below) optional(U&& u) noexcept(see below);
|
|
template<class U>
|
|
constexpr explicit(see below) optional(optional<U>& rhs) noexcept(see below);
|
|
template<class U>
|
|
constexpr explicit(see below) optional(const optional<U>& rhs) noexcept(see below);
|
|
template<class U>
|
|
constexpr explicit(see below) optional(optional<U>&& rhs) noexcept(see below);
|
|
template<class U>
|
|
constexpr explicit(see below) optional(const optional<U>&& rhs) noexcept(see below);
|
|
|
|
constexpr ~optional() = default;
|
|
|
|
// [optional.ref.assign], assignment
|
|
constexpr optional& operator=(nullopt_t) noexcept;
|
|
constexpr optional& operator=(const optional& rhs) noexcept = default;
|
|
|
|
template<class U> constexpr T& emplace(U&& u) noexcept(see below);
|
|
|
|
// [optional.ref.swap], swap
|
|
constexpr void swap(optional& rhs) noexcept;
|
|
|
|
// [optional.ref.iterators], iterator support
|
|
constexpr iterator begin() const noexcept;
|
|
constexpr iterator end() const noexcept;
|
|
|
|
// [optional.ref.observe], observers
|
|
constexpr T* operator->() const noexcept;
|
|
constexpr T& operator*() const noexcept;
|
|
constexpr explicit operator bool() const noexcept;
|
|
constexpr bool has_value() const noexcept;
|
|
constexpr T& value() const; // freestanding-deleted
|
|
template<class U = remove_cv_t<T>>
|
|
constexpr remove_cv_t<T> value_or(U&& u) const;
|
|
|
|
// [optional.ref.monadic], monadic operations
|
|
template<class F> constexpr auto and_then(F&& f) const;
|
|
template<class F> constexpr optional<invoke_result_t<F, T&>> transform(F&& f) const;
|
|
template<class F> constexpr optional or_else(F&& f) const;
|
|
|
|
// [optional.ref.mod], modifiers
|
|
constexpr void reset() noexcept;
|
|
|
|
private:
|
|
T* val = nullptr; // exposition only
|
|
|
|
// [optional.ref.expos], exposition only helper functions
|
|
template<class U>
|
|
constexpr void convert-ref-init-val(U&& u); // exposition only
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
*/
|
|
|
|
#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
|
|
# include <__cxx03/__config>
|
|
#else
|
|
# include <__config>
|
|
# include <version>
|
|
|
|
# include <__optional/common.h>
|
|
# include <__optional/comparison.h>
|
|
# include <__optional/hash.h>
|
|
# include <__optional/make_optional.h>
|
|
# include <__optional/optional.h>
|
|
# include <__optional/optional_ref.h>
|
|
# include <__optional/swap.h>
|
|
|
|
// TODO: Some headers rely on these transitive includes
|
|
# include <__cstddef/size_t.h>
|
|
# include <__type_traits/conditional.h>
|
|
# include <__type_traits/enable_if.h>
|
|
# include <__type_traits/invoke.h>
|
|
# include <__type_traits/is_constructible.h>
|
|
# include <__type_traits/is_object.h>
|
|
# include <__type_traits/is_reference.h>
|
|
# include <__type_traits/remove_const.h>
|
|
# include <__type_traits/remove_cvref.h>
|
|
# include <__utility/declval.h>
|
|
# include <__utility/forward.h>
|
|
# include <__utility/in_place.h>
|
|
# include <__utility/move.h>
|
|
|
|
# include <initializer_list>
|
|
|
|
// standard-mandated includes
|
|
// [optional.syn]
|
|
# include <compare>
|
|
|
|
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
# endif
|
|
|
|
# if defined(_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23) && _LIBCPP_STD_VER <= 20
|
|
# include <atomic>
|
|
# include <climits>
|
|
# include <concepts>
|
|
# include <ctime>
|
|
# include <iterator>
|
|
# include <limits>
|
|
# include <memory>
|
|
# include <ratio>
|
|
# include <stdexcept>
|
|
# include <tuple>
|
|
# include <type_traits>
|
|
# include <typeinfo>
|
|
# include <utility>
|
|
# include <variant>
|
|
# endif
|
|
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
|
|
|
|
#endif // _LIBCPP_OPTIONAL
|