template<class Arg>
constexpr explicit optional(in_place_t, Arg&& arg);
template<class U>
constexpr explicit(!is_convertible_v<U, T&>)
optional(U&& u) noexcept(is_nothrow_constructible_v<T&, U>);
template<class U>
constexpr explicit(!is_convertible_v<U&, T&>)
optional(optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, U&>);
template<class U>
constexpr explicit(!is_convertible_v<const U&, T&>)
optional(const optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, const U&>);
template<class U>
constexpr explicit(!is_convertible_v<U, T&>)
optional(optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, U>);
template<class U>
constexpr explicit(!is_convertible_v<const U, T&>)
optional(const optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, const U>);
constexpr optional& operator=(nullopt_t) noexcept;
template<class U>
constexpr T& emplace(U&& u) noexcept(is_nothrow_constructible_v<T&, U>);
constexpr void swap(optional& rhs) noexcept;
using iterator = implementation-defined; // present only if T is an object type other than an array
// of unknown bound
constexpr auto begin() const noexcept;
constexpr auto end() const noexcept;
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;
template<class U = remove_cv_t<T>> constexpr remove_cv_t<T> value_or(U&& u) const;
template<class F> constexpr auto and_then(F&& f) const;
template<class F>
constexpr optional<remove_cv_t<invoke_result_t<F, T&>>> transform(F&& f) const;
template<class F> constexpr optional or_else(F&& f) const;
constexpr void reset() noexcept;
template<class U>
constexpr void convert-ref-init-val(U&& u); // exposition only