[libcxx-commits] [libcxx] [libc++] Granularize `<optional>` (PR #206644)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 29 21:53:20 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: William Tran-Viet (smallp-o-p)

<details>
<summary>Changes</summary>

Ccertain 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.

---

Patch is 136.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/206644.diff


16 Files Affected:

- (modified) libcxx/include/CMakeLists.txt (+8) 
- (added) libcxx/include/__fwd/optional.h (+36) 
- (added) libcxx/include/__optional/common.h (+97) 
- (added) libcxx/include/__optional/comparison.h (+347) 
- (added) libcxx/include/__optional/hash.h (+48) 
- (added) libcxx/include/__optional/nullopt_t.h (+40) 
- (added) libcxx/include/__optional/optional.h (+761) 
- (added) libcxx/include/__optional/optional_ref.h (+355) 
- (added) libcxx/include/__optional/swap.h (+45) 
- (modified) libcxx/include/module.modulemap.in (+19) 
- (modified) libcxx/include/optional (+16-1416) 
- (modified) libcxx/test/std/experimental/iterator/ostream.joiner/ostream.joiner.ops/ostream_joiner.op.assign.pass.cpp (+1) 
- (modified) libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp (+1) 
- (modified) libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ctor.verify.cpp (+12-12) 
- (modified) libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/deduct.verify.cpp (+1-1) 
- (modified) libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.verify.cpp (+13-13) 


``````````diff
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cec9ba06a7a6d..021d392e50c78 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -468,6 +468,7 @@ set(files
   __fwd/mdspan.h
   __fwd/memory.h
   __fwd/memory_resource.h
+  __fwd/optional.h
   __fwd/ostream.h
   __fwd/pair.h
   __fwd/queue.h
@@ -661,6 +662,13 @@ set(files
   __numeric/transform_exclusive_scan.h
   __numeric/transform_inclusive_scan.h
   __numeric/transform_reduce.h
+  __optional/common.h
+  __optional/comparison.h
+  __optional/hash.h
+  __optional/nullopt_t.h
+  __optional/optional.h
+  __optional/optional_ref.h
+  __optional/swap.h
   __ostream/basic_ostream.h
   __ostream/print.h
   __ostream/put_character_sequence.h
diff --git a/libcxx/include/__fwd/optional.h b/libcxx/include/__fwd/optional.h
new file mode 100644
index 0000000000000..35a3d2ea11e74
--- /dev/null
+++ b/libcxx/include/__fwd/optional.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// std::optional<T&>
+
+#ifndef _LIBCPP___FWD_OPTIONAL_H
+#define _LIBCPP___FWD_OPTIONAL_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp>
+class optional;
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___FWD_OPTIONAL_H
diff --git a/libcxx/include/__optional/common.h b/libcxx/include/__optional/common.h
new file mode 100644
index 0000000000000..2b4862cfd9d34
--- /dev/null
+++ b/libcxx/include/__optional/common.h
@@ -0,0 +1,97 @@
+// -*- 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_COMMON_H
+#define _LIBCPP_OPTIONAL_COMMON_H
+
+#include <__assert>
+#include <__config>
+#include <__exception/exception.h>
+#include <__fwd/format.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/enable_view.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_object.h>
+#include <__type_traits/is_reference.h>
+
+#include <__fwd/optional.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+namespace std // purposefully not using versioning namespace
+{
+
+class _LIBCPP_EXPORTED_FROM_ABI bad_optional_access : public exception {
+public:
+  bad_optional_access() _NOEXCEPT                                      = default;
+  bad_optional_access(const bad_optional_access&) _NOEXCEPT            = default;
+  bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default;
+  // Get the key function ~bad_optional_access() into the dylib
+  ~bad_optional_access() _NOEXCEPT override;
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
+};
+
+} // namespace std
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+[[noreturn]] inline void __throw_bad_optional_access() {
+#  if _LIBCPP_HAS_EXCEPTIONS
+  throw bad_optional_access();
+#  else
+  _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
+#  endif
+}
+
+struct __optional_construct_from_invoke_tag {};
+
+template <class _Tp>
+struct __is_std_optional : false_type {};
+
+template <class _Tp>
+struct __is_std_optional<optional<_Tp>> : true_type {};
+
+template<class _Tp, bool = is_reference_v<_Tp>>
+struct __optional_storage_base;
+
+#    if _LIBCPP_STD_VER < 26
+template <class _Tp>
+inline constexpr bool __is_valid_optional_contained_type = is_object_v<_Tp>;
+#    else
+template <class _Tp>
+inline constexpr bool __is_valid_optional_contained_type = is_object_v<_Tp> || is_lvalue_reference_v<_Tp>;
+#    endif
+
+#    if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+
+template <class _Tp>
+constexpr bool ranges::enable_view<optional<_Tp>> = true;
+
+template <class _Tp>
+constexpr range_format format_kind<optional<_Tp>> = range_format::disabled;
+
+template <class _Tp>
+constexpr bool ranges::enable_borrowed_range<optional<_Tp&>> = true;
+
+#    endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+
+#endif
diff --git a/libcxx/include/__optional/comparison.h b/libcxx/include/__optional/comparison.h
new file mode 100644
index 0000000000000..10c109fac7605
--- /dev/null
+++ b/libcxx/include/__optional/comparison.h
@@ -0,0 +1,347 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COMPARISON_H
+#define _LIBCPP_OPTIONAL_COMPARISON_H
+
+#include <__compare/compare_three_way_result.h>
+#include <__compare/ordering.h>
+#include <__compare/three_way_comparable.h>
+#include <__config>
+#include <__optional/nullopt_t.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_core_convertible.h>
+#include <__type_traits/is_swappable.h>
+#include <__utility/declval.h>
+
+#include <__fwd/optional.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr 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;
+}
+
+#  if _LIBCPP_STD_VER >= 20
+
+template <class _Tp, three_way_comparable_with<_Tp> _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
+operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
+  if (__x && __y)
+    return *__x <=> *__y;
+  return __x.has_value() <=> __y.has_value();
+}
+
+#  endif // _LIBCPP_STD_VER >= 20
+
+// [optional.nullops] Comparison with nullopt
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, std::nullopt_t) noexcept {
+  return !static_cast<bool>(__x);
+}
+
+#  if _LIBCPP_STD_VER <= 17
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept {
+  return !static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept {
+  return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept {
+  return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept {
+  return false;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept {
+  return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept {
+  return !static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept {
+  return true;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept {
+  return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept {
+  return false;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept {
+  return true;
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept {
+  return !static_cast<bool>(__x);
+}
+
+#  else // _LIBCPP_STD_VER <= 17
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
+  return __x.has_value() <=> false;
+}
+
+#  endif // _LIBCPP_STD_VER <= 17
+
+// [optional.comp.with.t] Comparison with T
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x == __v;
+  return false;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v == *__x;
+  return false;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x != __v;
+  return true;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v != *__x;
+  return true;
+}
+
+template < class _Tp,
+           class _Up,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x < __v;
+  return true;
+}
+
+template < class _Tp,
+           class _Up,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v < *__x;
+  return false;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x <= __v;
+  return true;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v <= *__x;
+  return false;
+}
+
+template < class _Tp,
+           class _Up,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x > __v;
+  return false;
+}
+
+template < class _Tp,
+           class _Up,
+           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v > *__x;
+  return true;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const _Up& __v) {
+  if (__x.has_value())
+    return *__x >= __v;
+  return false;
+}
+
+template <
+    class _Tp,
+    class _Up,
+    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
+                int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __v, const optional<_Up>& __x) {
+  if (__x.has_value())
+    return __v >= *__x;
+  return true;
+}
+
+#  if _LIBCPP_STD_VER >= 20
+
+template <class _Tp>
+concept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
+
+template <class _Tp, class _Up>
+  requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
+_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
+operator<=>(const optional<_Tp>& __x, const _Up& __v) {
+  return __x.has_value() ? *__x <=> __v : strong_ordering::less;
+}
+
+#  endif // _LIBCPP_STD_VER >= 20
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+
+#endif
diff --git a/libcxx/include/__optional/hash.h b/libcxx/include/__optional/hash.h
new file mode 100644
index 0000000000000..830f99b0b855f
--- /dev/null
+++ b/libcxx/include/__optional/hash.h
@@ -0,0 +1,48 @@
+// -*- 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_HASH_H
+#define _LIBCPP_OPTIONAL_HASH_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
+#include <__type_traits/remove_const.h>
+
+#include <__fwd/optional.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp>
+struct hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > {
+#  if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
+  _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
+  _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
+#  endif
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const {
+    return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
+  }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+#endif // _LIBCPP_OPTIONAL_HASH_H
diff --git a/libcxx/include/__optional/nullopt_t.h b/libcxx/include/__optional/nullopt_t.h
new file mode 100644
index 0000000000000..bd66923f026b8
--- /dev/null
+++ b/libcxx/include/__optional/nullopt_t.h
@@ -0,0 +1,40 @@
+// -*- 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_NULLOPT_T_H
+#define _LIBCPP_OPTIONAL_NULLOPT_T_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+struct nullopt_t {
+  struct __secret_tag {
+    explicit __secret_tag() = default;
+  };
+  constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+};
+
+inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+#endif
diff --git a/libcxx/include/__optional/optional.h b/libcxx/include/__optional/optional.h
new file mode 100644
index 0000000000000..d01d8e661bdca
--- /dev/null
+++ b/libcxx/include/__optional/optional.h
@@ -0,0 +1,761 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// std::optional<T>
+
+#ifndef _LIBCPP_OPTIONAL_OPTIONAL_H
+#define _LIBCPP_OPTIONAL_OPTIONAL_H
+
+#include <__assert>
+#include <__concepts/invocable.h>
+#include <__config>
+#include <__functional/invoke.h>
+#include <__iterator/bounded_iter.h>
+#include <__iterator/capacity_aware_iterator.h>
+#include <__memory/addressof.h>
+#include <__memory/construct_at.h>
+#include <__tuple/sfinae_helpers.h>
+#include <__type_traits/add_pointer.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/conjunction.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/disjunction.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/i...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/206644


More information about the libcxx-commits mailing list