[libcxx-commits] [libcxx] [libc++] Reimplement `optional<T&>` as a partial specialization (PR #201983)

William Tran-Viet via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jun 10 20:47:11 PDT 2026


https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/201983

>From c682ab4917fecf2f6dd56bd899312cce08a49443 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 20 May 2026 20:14:31 -0400
Subject: [PATCH 1/7] Reimplement optional<T&> as a partial specialization

---
 libcxx/include/optional                       | 355 +++++++++---------
 .../optional.monadic/and_then.pass.cpp        |  37 +-
 .../optional.monadic/or_else.pass.cpp         |   8 +
 .../optional.monadic/transform.pass.cpp       |  21 +-
 .../optional_in_place_t.verify.cpp            |   8 +-
 .../optional_nullopt_t.verify.cpp             |  11 +-
 6 files changed, 250 insertions(+), 190 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index d0ddd2c0b8ea2..a5a98425c88ae 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -558,7 +558,7 @@ struct __optional_storage_base<_Tp, true> {
   _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
 
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) noexcept {
+  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) {
     _Tp& __r(std::forward<_Up>(__val));
     __value_ = std::addressof(__r);
   }
@@ -571,6 +571,14 @@ struct __optional_storage_base<_Tp, true> {
     __convert_init_ref_val(std::forward<_UArg>(__uarg));
   }
 
+#    if _LIBCPP_STD_VER >= 23
+  template <class _Fp, class... _Args>
+  constexpr __optional_storage_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) {
+    _Tp& __r = std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...);
+    __value_ = std::addressof(__r);
+  }
+#    endif
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
@@ -579,7 +587,6 @@ struct __optional_storage_base<_Tp, true> {
 
   template <class _UArg>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {
-    _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
     static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                   "Attempted to construct a reference element in tuple from a "
                   "possible temporary");
@@ -726,8 +733,8 @@ using __optional_sfinae_ctor_base_t _LIBCPP_NODEBUG =
 
 template <class _Tp>
 using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
-    __sfinae_assign_base< (is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Tp>) || is_lvalue_reference_v<_Tp>,
-                          (is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp>) || is_lvalue_reference_v<_Tp>>;
+    __sfinae_assign_base< (is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Tp>),
+                          (is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp>)>;
 
 template <class _Tp>
 class optional;
@@ -769,6 +776,7 @@ inline constexpr bool __is_constructible_for_optional_initializer_list_v =
 #    if _LIBCPP_STD_VER >= 26
 template <class _Tp, class... _Args>
 inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Args...> = false;
+
 template <class _Tp, class _Arg>
 inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Arg> =
     is_constructible_v<_Tp&, _Arg> && !reference_constructs_from_temporary_v<_Tp&, _Arg>;
@@ -777,6 +785,14 @@ template <class _Tp, class _Up, class... _Args>
 inline constexpr bool __is_constructible_for_optional_initializer_list_v<_Tp&, _Up, _Args...> = false;
 #    endif
 
+#    if _LIBCPP_STD_VER >= 26
+template <class _Tp>
+inline constexpr bool __is_valid_optional_type = std::is_object_v<_Tp> || std::is_lvalue_reference_v<_Tp>;
+#    else
+template <class _Tp>
+inline constexpr bool __is_valid_optional_type = std::is_object_v<_Tp>;
+#    endif
+
 template <class _Tp, class = void>
 struct __optional_iterator_base : __optional_move_assign_base<_Tp> {
   using __optional_move_assign_base<_Tp>::__optional_move_assign_base;
@@ -878,9 +894,8 @@ public:
       conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
 
 private:
-  static_assert(!is_same_v<__remove_cvref_t<_Tp>, in_place_t>,
-                "instantiation of optional with in_place_t is ill-formed");
-  static_assert(!is_same_v<__remove_cvref_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
+  static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>, "instantiation of optional with in_place_t is ill-formed");
+  static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
 #    if _LIBCPP_STD_VER >= 26
   static_assert(!is_rvalue_reference_v<_Tp>, "instantiation of optional with an rvalue reference type is ill-formed");
 #    else
@@ -889,16 +904,6 @@ private:
   static_assert(is_destructible_v<_Tp>, "instantiation of optional with a non-destructible type is ill-formed");
   static_assert(!is_array_v<_Tp>, "instantiation of optional with an array type is ill-formed");
 
-#    if _LIBCPP_STD_VER >= 26
-  template <class _Up>
-  constexpr static bool __libcpp_opt_ref_ctor_deleted =
-      is_lvalue_reference_v<_Tp> && reference_constructs_from_temporary_v<_Tp, _Up>;
-
-  template <class _Up>
-  constexpr static bool __ref_ctor_enabled =
-      is_lvalue_reference_v<_Tp> && !reference_constructs_from_temporary_v<_Tp, _Up>;
-#    endif
-
   // LWG2756: conditionally explicit conversion from _Up
   struct _CheckOptionalArgsConstructor {
     template <class _Up>
@@ -984,117 +989,34 @@ public:
       : __base(in_place, __il, std::forward<_Args>(__args)...) {}
 
   template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
-#    endif
-      : __base(in_place, std::forward<_Up>(__v)) {
-  }
+  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
 
   template <class _Up                                                                        = remove_cv_t<_Tp>,
             enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
-#    endif
-      : __base(in_place, std::forward<_Up>(__v)) {
-  }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
 
   // LWG2756: conditionally explicit conversion from const optional<_Up>&
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
-#    endif
-  {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
     this->__construct_from(__v);
   }
+
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
-#    endif
-  {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
     this->__construct_from(__v);
   }
 
   // LWG2756: conditionally explicit conversion from optional<_Up>&&
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
-#    endif
-  {
-    this->__construct_from(std::move(__v));
-  }
-  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
-#    endif
-  {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
     this->__construct_from(std::move(__v));
   }
 
-  // deleted optional<T&> constructors and additional optional<T&> constructors
-#    if _LIBCPP_STD_VER >= 26
-  // optional(U&&)
-  template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<_Up>
-  optional(_Up&&) = delete;
-
-  template <class _Up                                                                        = remove_cv_t<_Tp>,
-            enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<_Up>
-  explicit optional(_Up&&) = delete;
-
-  // optional(optional<U>& rhs)
-  template <class _Up>
-    requires __ref_ctor_enabled<_Up&> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) &&
-             is_constructible_v<_Tp&, _Up&>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
-      optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
-    this->__construct_from(__rhs);
-  }
-
-  template <class _Up>
-    requires __libcpp_opt_ref_ctor_deleted<_Up&> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
-                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
-  constexpr explicit optional(optional<_Up>& __rhs) noexcept = delete;
-
-  // optional(const optional<U>&)
-  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<const _Up&>
-  optional(const optional<_Up>&) = delete;
-
-  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<const _Up&>
-  explicit optional(const optional<_Up>&) = delete;
-
-  // optional(optional<U>&&)
-  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<_Up>
-  optional(optional<_Up>&&) = delete;
-
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<_Up>
-  explicit optional(optional<_Up>&&) = delete;
-
-  // optional(const optional<U>&&)
-  template <class _Up>
-    requires __ref_ctor_enabled<const _Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
-             (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<const _Up, _Tp&>)
-      optional(const optional<_Up>&& __v) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
     this->__construct_from(std::move(__v));
   }
 
-  template <class _Up>
-    requires __libcpp_opt_ref_ctor_deleted<const _Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
-                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>&& __v) noexcept = delete;
-#    endif
-
 #    if _LIBCPP_STD_VER >= 23
   template <class _Tag,
             class _Fp,
@@ -1117,8 +1039,7 @@ public:
             enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
                              _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
                              is_constructible<_Tp, _Up>,
-                             is_assignable<_Tp&, _Up>,
-                             is_object<_Tp>>::value,
+                             is_assignable<_Tp&, _Up>>::value,
                         int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
     if (this->has_value())
@@ -1143,11 +1064,7 @@ public:
   }
 
   template <class... _Args, enable_if_t<__is_constructible_for_optional_v<_Tp, _Args...>, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args)
-#    if _LIBCPP_STD_VER >= 26
-      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp, _Args...>)
-#    endif
-  {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
     reset();
     this->__construct(std::forward<_Args>(__args)...);
     return this->__get();
@@ -1162,12 +1079,8 @@ public:
     return this->__get();
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt) noexcept(
-      (is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>)
-#    if _LIBCPP_STD_VER >= 26
-      || is_lvalue_reference_v<_Tp>
-#    endif
-  ) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+  swap(optional& __opt) noexcept((is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>)) {
     this->__swap(__opt);
   }
 
@@ -1181,9 +1094,6 @@ public:
   using __base::value;
 
   template <class _Up = remove_cv_t<_Tp>>
-#    if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#    endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
@@ -1191,9 +1101,6 @@ public:
   }
 
   template <class _Up = remove_cv_t<_Tp>>
-#    if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#    endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
@@ -1202,9 +1109,6 @@ public:
 
 #    if _LIBCPP_STD_VER >= 23
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
     using _Up = invoke_result_t<_Func, _Tp&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1215,9 +1119,6 @@ public:
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
     using _Up = invoke_result_t<_Func, const _Tp&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1228,9 +1129,6 @@ public:
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
     using _Up = invoke_result_t<_Func, _Tp&&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1241,9 +1139,6 @@ public:
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
     using _Up = invoke_result_t<_Func, const _Tp&&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1254,60 +1149,48 @@ public:
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
+    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
     return optional<_Up>();
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
+    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
     return optional<_Up>();
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
-    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
+    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
     return optional<_Up>();
   }
 
   template <class _Func>
-#      if _LIBCPP_STD_VER >= 26
-    requires(is_object_v<_Tp>)
-#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
-    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
+    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
     return optional<_Up>();
@@ -1316,9 +1199,6 @@ public:
   template <invocable _Func>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
     requires is_copy_constructible_v<_Tp>
-#      if _LIBCPP_STD_VER >= 26
-             && (is_object_v<_Tp>)
-#      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
                   "Result of f() should be the same type as this optional");
@@ -1330,9 +1210,6 @@ public:
   template <invocable _Func>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
     requires is_move_constructible_v<_Tp>
-#      if _LIBCPP_STD_VER >= 26
-             && (is_object_v<_Tp>)
-#      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
                   "Result of f() should be the same type as this optional");
@@ -1343,24 +1220,136 @@ public:
 #    endif // _LIBCPP_STD_VER >= 23
 
   using __base::reset;
+};
 
-// optional<T&> overloads
 #    if _LIBCPP_STD_VER >= 26
+template <class _Tp>
+class optional<_Tp&> : public __optional_iterator_base<_Tp&> {
+  using __base _LIBCPP_NODEBUG = __optional_iterator_base<_Tp&>;
+
+  template <class _Up, class _QualUp>
+  static constexpr bool __check_optionalU_ctor =
+      !std::is_same_v<std::remove_cv_t<_Tp>, optional<_Up>> && !std::is_same_v<_Tp&, _Up> &&
+      std::is_constructible_v<_Tp&, _QualUp>;
+  static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>, "instantiation of optional with in_place_t is ill-formed");
+  static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
+
+public:
+  using value_type = _Tp;
+
+  constexpr optional() noexcept = default;
+  constexpr optional(nullopt_t) noexcept {}
+  constexpr optional(const optional&) noexcept = default;
+
+  template <class _Arg>
+    requires(std::is_constructible_v<_Tp&, _Arg> && !std::reference_constructs_from_temporary_v<_Tp&, _Arg>)
+  constexpr explicit optional(in_place_t, _Arg&& __arg) : __base(in_place, std::forward<_Arg>(__arg)) {}
+
+  template <class _Up>
+    requires(!std::is_same_v<std::remove_cvref_t<_Up>, optional> && !is_same_v<std::remove_cvref_t<_Up>, in_place_t> &&
+             is_constructible_v<_Tp&, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr explicit(!is_convertible_v<_Up, _Tp&>) optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
+      : __base(in_place, std::forward<_Up>(__v)) {}
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, _Up&> && !std::reference_constructs_from_temporary_v<_Tp&, _Up&>)
+  constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
+      optional(optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up&>) {
+    this->__construct_from(__rhs);
+  }
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, const _Up&> && !std::reference_constructs_from_temporary_v<_Tp&, const _Up&>)
+  constexpr explicit(!is_convertible_v<const _Up&, _Tp&>)
+      optional(const optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up&>) {
+    this->__construct_from(__rhs);
+  }
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr explicit(!is_convertible_v<_Up, _Tp&>)
+      optional(optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) {
+    this->__construct_from(std::move(__rhs));
+  }
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, const _Up> && !std::reference_constructs_from_temporary_v<_Tp&, const _Up>)
+  constexpr explicit(!is_convertible_v<const _Up, _Tp&>)
+      optional(const optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up>) {
+    this->__construct_from(std::move(__rhs));
+  }
+
+  template <class _Tag, class _Fp, class... _Args>
+    requires(std::is_same_v<_Tag, __optional_construct_from_invoke_tag>)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
+      : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
+
+  // deleted overloads
+
+  template <class _Up>
+    requires(!std::is_same_v<std::remove_cvref_t<_Up>, optional> && !is_same_v<std::remove_cvref_t<_Up>, in_place_t> &&
+             is_constructible_v<_Tp&, _Up> && std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr explicit(!is_convertible_v<_Up, _Tp&>)
+      optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) = delete;
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, _Up&> && std::reference_constructs_from_temporary_v<_Tp&, _Up&>)
+  constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
+      optional(optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up&>) = delete;
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, const _Up&> && std::reference_constructs_from_temporary_v<_Tp&, const _Up&>)
+  constexpr explicit(!is_convertible_v<const _Up&, _Tp&>)
+      optional(const optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up&>) = delete;
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, _Up> && std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr explicit(!is_convertible_v<_Up, _Tp&>)
+      optional(optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) = delete;
+
+  template <class _Up>
+    requires(__check_optionalU_ctor<_Up, const _Up> && std::reference_constructs_from_temporary_v<_Tp&, const _Up>)
+  constexpr explicit(!is_convertible_v<const _Up, _Tp&>)
+      optional(const optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up>) = delete;
+
+  constexpr ~optional() = default;
+
+  using __base::__get;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(nullopt_t) noexcept {
+    reset();
+    return *this;
+  }
+
+  constexpr optional& operator=(const optional&) noexcept = default;
+
+  template <class _Up>
+    requires(is_constructible_v<_Tp&, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr _Tp& emplace(_Up&& __u) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) {
+    this->__construct(std::forward<_Up>(__u));
+
+    return this->__get();
+  }
+
+  constexpr void swap(optional& __rhs) noexcept { this->__swap(__rhs); }
+
+  using __base::operator->;
+  using __base::operator*;
+  constexpr explicit operator bool() const noexcept { return has_value(); }
+  using __base::has_value;
+  using __base::value;
 
   template <class _Up = remove_cvref_t<_Tp>>
-    requires(is_lvalue_reference_v<_Tp> && is_object_v<__libcpp_remove_reference_t<_Tp>> &&
-             !is_array_v<__libcpp_remove_reference_t<_Tp>>)
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decay_t<_Tp> value_or(_Up&& __v) const {
-    static_assert(
-        is_constructible_v<remove_cvref_t<_Tp>, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
-    static_assert(
-        is_convertible_v<_Up, remove_cvref_t<_Tp>>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
-    return this->has_value() ? this->__get() : static_cast<remove_cvref_t<_Tp>>(std::forward<_Up>(__v));
+    requires(!std::is_array_v<_Tp> && std::is_object_v<_Tp>)
+  [[nodiscard]] constexpr decay_t<_Tp> value_or(_Up&& __v) const {
+    using _XTp = std::remove_cv_t<_Tp>;
+    static_assert(std::is_constructible_v<_XTp, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
+    static_assert(std::is_convertible_v<_Up, _XTp>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
+    return this->has_value() ? this->__get() : static_cast<_XTp>(std::forward<_Up>(__v));
   }
 
   template <class _Func>
-    requires(is_lvalue_reference_v<_Tp>)
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const {
+  [[nodiscard]] constexpr auto and_then(_Func&& __f) const {
     using _Up = invoke_result_t<_Func, _Tp&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
                   "Result of f(value()) must be a specialization of std::optional");
@@ -1370,30 +1359,30 @@ public:
   }
 
   template <class _Func>
-    requires(is_lvalue_reference_v<_Tp>)
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional<remove_cv_t<invoke_result_t<_Func, _Tp&>>>
-  transform(_Func&& __f) const {
-    using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
+  [[nodiscard]] constexpr optional<remove_cv_t<invoke_result_t<_Func, _Tp&>>> transform(_Func&& __f) const {
+    using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
+    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
     return optional<_Up>();
   }
 
   template <invocable _Func>
-    requires(is_lvalue_reference_v<_Tp>)
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const {
+  [[nodiscard]] constexpr optional or_else(_Func&& __f) const {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
                   "Result of f() should be the same type as this optional");
     if (*this)
       return *this;
     return std::forward<_Func>(__f)();
   }
-#    endif
+
+  using __base::reset;
 };
+#    endif
 
 template <class _Tp>
 optional(_Tp) -> optional<_Tp>;
@@ -1702,7 +1691,13 @@ operator<=>(const optional<_Tp>& __x, const _Up& __v) {
 
 #    endif // _LIBCPP_STD_VER >= 20
 
-template <class _Tp, enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, int> = 0>
+template <class _Tp,
+          enable_if_t<(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)
+#    if _LIBCPP_STD_VER >= 26
+                          || is_reference_v<_Tp>
+#    endif
+                      ,
+                      int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI
 _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
   __x.swap(__y);
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
index 93bbd74cd8678..e806cd8dd5343 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
@@ -261,8 +261,6 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
-  // Test "overloads", only the const (no ref-qualifier) and_then() should be called
-
   { // &
     // Without & qualifier on F's operator()
     {
@@ -339,6 +337,41 @@ constexpr bool test_ref() {
       assert(std::move(i).and_then(std::move(nl)) == std::nullopt);
     }
   }
+
+  {
+    int i = 1;
+    int j = 2;
+    {
+      std::optional<int&> o(i);
+      std::same_as<std::optional<int&>> decltype(auto) r = o.and_then([&](auto&& ii) {
+        ii += j;
+        return std::optional<int&>(ii);
+      });
+
+      assert(i == 3);
+      assert(r == 3);
+    }
+    {
+      const std::optional<int&> o(i);
+      std::same_as<std::optional<int&>> decltype(auto) r = o.and_then([&](auto&& ii) {
+        ii += j;
+        return std::optional<int&>(ii);
+      });
+
+      assert(i == 5);
+      assert(r == 5);
+    }
+    {
+      std::optional<int&> o{};
+      std::same_as<std::optional<int>> decltype(auto) r = o.and_then([&](auto&&) { return std::optional(1); });
+      assert(r == std::nullopt);
+    }
+    {
+      const std::optional<int&> o{};
+      std::same_as<std::optional<int>> decltype(auto) r = o.and_then([&](auto&&) { return std::optional(1); });
+      assert(r == std::nullopt);
+    }
+  }
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
index 326013cd6557f..7252f0a8700df 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
@@ -104,6 +104,14 @@ constexpr bool test() {
     }) == i);
   }
 
+  {
+    int j = 2;
+    std::optional<int&> opt;
+    std::same_as<std::optional<int&>> decltype(auto) o = opt.or_else([&] { return std::optional<int&>(j); });
+    assert(o == j);
+    assert(&(*o) == &j);
+  }
+
 #endif
 
   return true;
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index b8536b790f749..96303c5796f6d 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -204,8 +204,6 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
-  // Test that no matter the ref qualifier on the object .transform() is invoked on, only the added
-  // const (no ref-qualifier) overload is used
   {
     std::optional<int&> opt1;
     std::same_as<std::optional<int>> decltype(auto) opt1r = opt1.transform([](int i) { return i + 2; });
@@ -229,7 +227,6 @@ constexpr bool test_ref() {
     assert(*o2 == 4.0f);
   }
 
-  // &
   {
     // Without & qualifier on F's operator()
     {
@@ -250,7 +247,6 @@ constexpr bool test_ref() {
       assert(*o3 == 1);
     }
   }
-  // const& overload
   {
     // Without & qualifier on F's operator()
     {
@@ -308,6 +304,23 @@ constexpr bool test_ref() {
     auto o6r               = o6.transform([](int) { return 42; });
     assert(!o6r);
   }
+
+  {
+    int i = 42;
+    int j{43};
+
+    auto func = [&j](int&) -> int& { return j; };
+
+    std::optional<int&> opt{i};
+    std::same_as<std::optional<int&>> decltype(auto) o = opt.transform(func);
+    assert(o == j);
+    assert(&(*o) == &j);
+
+    std::same_as<std::optional<int&>> decltype(auto) o2 = std::as_const(opt).transform(func);
+    assert(o2 == j);
+    assert(&(*o2) == &j);
+  }
+
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.verify.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.verify.cpp
index 20efef515c362..8731b0b37e9bc 100644
--- a/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.verify.cpp
@@ -15,7 +15,13 @@
 
 #include <optional>
 
+#include "test_macros.h"
+
 void f() {
     std::optional<std::in_place_t> opt; // expected-note {{requested here}}
-    // expected-error at optional:* {{instantiation of optional with in_place_t is ill-formed}}
+    // expected-error@*:* 1 {{instantiation of optional with in_place_t is ill-formed}}
+#if TEST_STD_VER >= 26
+    std::optional<std::in_place_t&> opt1; // expected-note {{requested here}}
+    // expected-error@*:* 1 {{instantiation of optional with in_place_t is ill-formed}}
+#endif
 }
diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.verify.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.verify.cpp
index f807da7470ae9..0054b05aa767c 100644
--- a/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.verify.cpp
@@ -15,10 +15,15 @@
 
 #include <optional>
 
+#include "test_macros.h"
+
 void f() {
     std::optional<std::nullopt_t> opt; // expected-note 1 {{requested here}}
     std::optional<const std::nullopt_t> opt1; // expected-note 1 {{requested here}}
-    std::optional<std::nullopt_t &> opt2; // expected-note 1 {{requested here}}
-    std::optional<std::nullopt_t &&> opt3; // expected-note 1 {{requested here}}
-    // expected-error at optional:* 4 {{instantiation of optional with nullopt_t is ill-formed}}
+    // expected-error@*:* 2 {{instantiation of optional with nullopt_t is ill-formed}}
+#if TEST_STD_VER >= 26
+    std::optional<std::nullopt_t&> opt2;       // expected-note 1 {{requested here}}
+    std::optional<const std::nullopt_t&> opt3; // expected-note 1 {{requested here}}
+    // expected-error@*:* 2 {{instantiation of optional with nullopt_t is ill-formed}}
+#endif
 }

>From 8e2749640288d6a61186b05d5b01e0e419be8a5c Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 5 Jun 2026 21:59:33 -0400
Subject: [PATCH 2/7] Missng test include

---
 .../std/utilities/optional/optional.monadic/or_else.pass.cpp     | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
index 7252f0a8700df..3a06ce24bfc99 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
@@ -15,6 +15,7 @@
 #include "MoveOnly.h"
 
 #include <cassert>
+#include <concepts>
 #include <optional>
 
 struct NonMovable {

>From 2ccfcec0e841e410e88bcba43ee4ad8e0629579f Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Jun 2026 18:53:16 -0400
Subject: [PATCH 3/7] kick CI


>From dabd9a90d0fe0ff5d0fab899de588dffa04cfe85 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Jun 2026 19:17:05 -0400
Subject: [PATCH 4/7] remove_cv_ref_t -> remove_cv_t

---
 libcxx/include/optional | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index a5a98425c88ae..4f190ae710527 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -1339,7 +1339,7 @@ public:
   using __base::has_value;
   using __base::value;
 
-  template <class _Up = remove_cvref_t<_Tp>>
+  template <class _Up = std::remove_cv_t<_Tp>>
     requires(!std::is_array_v<_Tp> && std::is_object_v<_Tp>)
   [[nodiscard]] constexpr decay_t<_Tp> value_or(_Up&& __v) const {
     using _XTp = std::remove_cv_t<_Tp>;

>From e43f983ead3894cedae66acafd0fcfc8e014cf27 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Jun 2026 22:21:12 -0400
Subject: [PATCH 5/7] Remove std:: qualification for type traits

---
 libcxx/include/optional | 67 +++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 4f190ae710527..95a7fcf57f202 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -787,10 +787,10 @@ inline constexpr bool __is_constructible_for_optional_initializer_list_v<_Tp&, _
 
 #    if _LIBCPP_STD_VER >= 26
 template <class _Tp>
-inline constexpr bool __is_valid_optional_type = std::is_object_v<_Tp> || std::is_lvalue_reference_v<_Tp>;
+inline constexpr bool __is_valid_optional_type = is_object_v<_Tp> || is_lvalue_reference_v<_Tp>;
 #    else
 template <class _Tp>
-inline constexpr bool __is_valid_optional_type = std::is_object_v<_Tp>;
+inline constexpr bool __is_valid_optional_type = is_object_v<_Tp>;
 #    endif
 
 template <class _Tp, class = void>
@@ -1229,8 +1229,7 @@ class optional<_Tp&> : public __optional_iterator_base<_Tp&> {
 
   template <class _Up, class _QualUp>
   static constexpr bool __check_optionalU_ctor =
-      !std::is_same_v<std::remove_cv_t<_Tp>, optional<_Up>> && !std::is_same_v<_Tp&, _Up> &&
-      std::is_constructible_v<_Tp&, _QualUp>;
+      !is_same_v<remove_cv_t<_Tp>, optional<_Up>> && !is_same_v<_Tp&, _Up> && is_constructible_v<_Tp&, _QualUp>;
   static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>, "instantiation of optional with in_place_t is ill-formed");
   static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
 
@@ -1242,75 +1241,75 @@ public:
   constexpr optional(const optional&) noexcept = default;
 
   template <class _Arg>
-    requires(std::is_constructible_v<_Tp&, _Arg> && !std::reference_constructs_from_temporary_v<_Tp&, _Arg>)
+    requires(is_constructible_v<_Tp&, _Arg> && !reference_constructs_from_temporary_v<_Tp&, _Arg>)
   constexpr explicit optional(in_place_t, _Arg&& __arg) : __base(in_place, std::forward<_Arg>(__arg)) {}
 
   template <class _Up>
-    requires(!std::is_same_v<std::remove_cvref_t<_Up>, optional> && !is_same_v<std::remove_cvref_t<_Up>, in_place_t> &&
-             is_constructible_v<_Tp&, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+    requires(!is_same_v<remove_cvref_t<_Up>, optional> && !is_same_v<remove_cvref_t<_Up>, in_place_t> &&
+             is_constructible_v<_Tp&, _Up> && !reference_constructs_from_temporary_v<_Tp&, _Up>)
   constexpr explicit(!is_convertible_v<_Up, _Tp&>) optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp&, _Up>)
       : __base(in_place, std::forward<_Up>(__v)) {}
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, _Up&> && !std::reference_constructs_from_temporary_v<_Tp&, _Up&>)
+    requires(__check_optionalU_ctor<_Up, _Up&> && !reference_constructs_from_temporary_v<_Tp&, _Up&>)
   constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
-      optional(optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up&>) {
+      optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
     this->__construct_from(__rhs);
   }
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, const _Up&> && !std::reference_constructs_from_temporary_v<_Tp&, const _Up&>)
+    requires(__check_optionalU_ctor<_Up, const _Up&> && !reference_constructs_from_temporary_v<_Tp&, const _Up&>)
   constexpr explicit(!is_convertible_v<const _Up&, _Tp&>)
-      optional(const optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up&>) {
+      optional(const optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, const _Up&>) {
     this->__construct_from(__rhs);
   }
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+    requires(__check_optionalU_ctor<_Up, _Up> && !reference_constructs_from_temporary_v<_Tp&, _Up>)
   constexpr explicit(!is_convertible_v<_Up, _Tp&>)
-      optional(optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) {
+      optional(optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) {
     this->__construct_from(std::move(__rhs));
   }
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, const _Up> && !std::reference_constructs_from_temporary_v<_Tp&, const _Up>)
+    requires(__check_optionalU_ctor<_Up, const _Up> && !reference_constructs_from_temporary_v<_Tp&, const _Up>)
   constexpr explicit(!is_convertible_v<const _Up, _Tp&>)
-      optional(const optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up>) {
+      optional(const optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
     this->__construct_from(std::move(__rhs));
   }
 
   template <class _Tag, class _Fp, class... _Args>
-    requires(std::is_same_v<_Tag, __optional_construct_from_invoke_tag>)
+    requires(is_same_v<_Tag, __optional_construct_from_invoke_tag>)
   _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
       : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
 
   // deleted overloads
 
   template <class _Up>
-    requires(!std::is_same_v<std::remove_cvref_t<_Up>, optional> && !is_same_v<std::remove_cvref_t<_Up>, in_place_t> &&
-             is_constructible_v<_Tp&, _Up> && std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+    requires(!is_same_v<remove_cvref_t<_Up>, optional> && !is_same_v<remove_cvref_t<_Up>, in_place_t> &&
+             is_constructible_v<_Tp&, _Up> && reference_constructs_from_temporary_v<_Tp&, _Up>)
   constexpr explicit(!is_convertible_v<_Up, _Tp&>)
       optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) = delete;
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, _Up&> && std::reference_constructs_from_temporary_v<_Tp&, _Up&>)
+    requires(__check_optionalU_ctor<_Up, _Up&> && reference_constructs_from_temporary_v<_Tp&, _Up&>)
   constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
-      optional(optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up&>) = delete;
+      optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) = delete;
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, const _Up&> && std::reference_constructs_from_temporary_v<_Tp&, const _Up&>)
+    requires(__check_optionalU_ctor<_Up, const _Up&> && reference_constructs_from_temporary_v<_Tp&, const _Up&>)
   constexpr explicit(!is_convertible_v<const _Up&, _Tp&>)
-      optional(const optional<_Up>& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up&>) = delete;
+      optional(const optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, const _Up&>) = delete;
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, _Up> && std::reference_constructs_from_temporary_v<_Tp&, _Up>)
+    requires(__check_optionalU_ctor<_Up, _Up> && reference_constructs_from_temporary_v<_Tp&, _Up>)
   constexpr explicit(!is_convertible_v<_Up, _Tp&>)
-      optional(optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) = delete;
+      optional(optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) = delete;
 
   template <class _Up>
-    requires(__check_optionalU_ctor<_Up, const _Up> && std::reference_constructs_from_temporary_v<_Tp&, const _Up>)
+    requires(__check_optionalU_ctor<_Up, const _Up> && reference_constructs_from_temporary_v<_Tp&, const _Up>)
   constexpr explicit(!is_convertible_v<const _Up, _Tp&>)
-      optional(const optional<_Up>&& __rhs) noexcept(std::is_nothrow_constructible_v<_Tp&, const _Up>) = delete;
+      optional(const optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) = delete;
 
   constexpr ~optional() = default;
 
@@ -1324,8 +1323,8 @@ public:
   constexpr optional& operator=(const optional&) noexcept = default;
 
   template <class _Up>
-    requires(is_constructible_v<_Tp&, _Up> && !std::reference_constructs_from_temporary_v<_Tp&, _Up>)
-  constexpr _Tp& emplace(_Up&& __u) noexcept(std::is_nothrow_constructible_v<_Tp&, _Up>) {
+    requires(is_constructible_v<_Tp&, _Up> && !reference_constructs_from_temporary_v<_Tp&, _Up>)
+  constexpr _Tp& emplace(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) {
     this->__construct(std::forward<_Up>(__u));
 
     return this->__get();
@@ -1335,16 +1334,18 @@ public:
 
   using __base::operator->;
   using __base::operator*;
+
   constexpr explicit operator bool() const noexcept { return has_value(); }
+
   using __base::has_value;
   using __base::value;
 
-  template <class _Up = std::remove_cv_t<_Tp>>
-    requires(!std::is_array_v<_Tp> && std::is_object_v<_Tp>)
+  template <class _Up = remove_cv_t<_Tp>>
+    requires(!is_array_v<_Tp> && is_object_v<_Tp>)
   [[nodiscard]] constexpr decay_t<_Tp> value_or(_Up&& __v) const {
-    using _XTp = std::remove_cv_t<_Tp>;
-    static_assert(std::is_constructible_v<_XTp, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
-    static_assert(std::is_convertible_v<_Up, _XTp>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
+    using _XTp = remove_cv_t<_Tp>;
+    static_assert(is_constructible_v<_XTp, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
+    static_assert(is_convertible_v<_Up, _XTp>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
     return this->has_value() ? this->__get() : static_cast<_XTp>(std::forward<_Up>(__v));
   }
 

>From 36c8a9a79a59f9dc5c5ce42e07607d024f15b2c4 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 10 Jun 2026 23:28:11 -0400
Subject: [PATCH 6/7] revert monadic bug fix

---
 libcxx/include/optional                       | 26 +++-----------
 .../optional.monadic/and_then.pass.cpp        | 36 ++-----------------
 .../optional.monadic/or_else.pass.cpp         |  8 -----
 .../optional.monadic/transform.pass.cpp       | 20 +++--------
 4 files changed, 11 insertions(+), 79 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 95a7fcf57f202..ed333a17246ab 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -571,14 +571,6 @@ struct __optional_storage_base<_Tp, true> {
     __convert_init_ref_val(std::forward<_UArg>(__uarg));
   }
 
-#    if _LIBCPP_STD_VER >= 23
-  template <class _Fp, class... _Args>
-  constexpr __optional_storage_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) {
-    _Tp& __r = std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...);
-    __value_ = std::addressof(__r);
-  }
-#    endif
-
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
@@ -785,14 +777,6 @@ template <class _Tp, class _Up, class... _Args>
 inline constexpr bool __is_constructible_for_optional_initializer_list_v<_Tp&, _Up, _Args...> = false;
 #    endif
 
-#    if _LIBCPP_STD_VER >= 26
-template <class _Tp>
-inline constexpr bool __is_valid_optional_type = is_object_v<_Tp> || is_lvalue_reference_v<_Tp>;
-#    else
-template <class _Tp>
-inline constexpr bool __is_valid_optional_type = is_object_v<_Tp>;
-#    endif
-
 template <class _Tp, class = void>
 struct __optional_iterator_base : __optional_move_assign_base<_Tp> {
   using __optional_move_assign_base<_Tp>::__optional_move_assign_base;
@@ -1154,7 +1138,7 @@ public:
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
     return optional<_Up>();
@@ -1166,7 +1150,7 @@ public:
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
     return optional<_Up>();
@@ -1178,7 +1162,7 @@ public:
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
-    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
     return optional<_Up>();
@@ -1190,7 +1174,7 @@ public:
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
-    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
     return optional<_Up>();
@@ -1365,7 +1349,7 @@ public:
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
-    static_assert(__is_valid_optional_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
+    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
 
     if (*this)
       return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
index e806cd8dd5343..ee38e2fd9e54a 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
@@ -261,6 +261,8 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
+  // Test "overloads", only the const (no ref-qualifier) and_then() should be called
+
   { // &
     // Without & qualifier on F's operator()
     {
@@ -338,40 +340,6 @@ constexpr bool test_ref() {
     }
   }
 
-  {
-    int i = 1;
-    int j = 2;
-    {
-      std::optional<int&> o(i);
-      std::same_as<std::optional<int&>> decltype(auto) r = o.and_then([&](auto&& ii) {
-        ii += j;
-        return std::optional<int&>(ii);
-      });
-
-      assert(i == 3);
-      assert(r == 3);
-    }
-    {
-      const std::optional<int&> o(i);
-      std::same_as<std::optional<int&>> decltype(auto) r = o.and_then([&](auto&& ii) {
-        ii += j;
-        return std::optional<int&>(ii);
-      });
-
-      assert(i == 5);
-      assert(r == 5);
-    }
-    {
-      std::optional<int&> o{};
-      std::same_as<std::optional<int>> decltype(auto) r = o.and_then([&](auto&&) { return std::optional(1); });
-      assert(r == std::nullopt);
-    }
-    {
-      const std::optional<int&> o{};
-      std::same_as<std::optional<int>> decltype(auto) r = o.and_then([&](auto&&) { return std::optional(1); });
-      assert(r == std::nullopt);
-    }
-  }
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
index 3a06ce24bfc99..2e7e9737803a4 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
@@ -105,14 +105,6 @@ constexpr bool test() {
     }) == i);
   }
 
-  {
-    int j = 2;
-    std::optional<int&> opt;
-    std::same_as<std::optional<int&>> decltype(auto) o = opt.or_else([&] { return std::optional<int&>(j); });
-    assert(o == j);
-    assert(&(*o) == &j);
-  }
-
 #endif
 
   return true;
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index 96303c5796f6d..ca7c6d9bbdc4e 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -204,6 +204,8 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
+  // Test that no matter the ref qualifier on the object .transform() is invoked on, only the added
+  // const (no ref-qualifier) overload is used
   {
     std::optional<int&> opt1;
     std::same_as<std::optional<int>> decltype(auto) opt1r = opt1.transform([](int i) { return i + 2; });
@@ -227,6 +229,7 @@ constexpr bool test_ref() {
     assert(*o2 == 4.0f);
   }
 
+  // &
   {
     // Without & qualifier on F's operator()
     {
@@ -247,6 +250,7 @@ constexpr bool test_ref() {
       assert(*o3 == 1);
     }
   }
+  // const& overload
   {
     // Without & qualifier on F's operator()
     {
@@ -305,22 +309,6 @@ constexpr bool test_ref() {
     assert(!o6r);
   }
 
-  {
-    int i = 42;
-    int j{43};
-
-    auto func = [&j](int&) -> int& { return j; };
-
-    std::optional<int&> opt{i};
-    std::same_as<std::optional<int&>> decltype(auto) o = opt.transform(func);
-    assert(o == j);
-    assert(&(*o) == &j);
-
-    std::same_as<std::optional<int&>> decltype(auto) o2 = std::as_const(opt).transform(func);
-    assert(o2 == j);
-    assert(&(*o2) == &j);
-  }
-
   return true;
 }
 #endif

>From a3c21a6ff5e50cce755fa66c6db42c2e6fb6dafc Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 10 Jun 2026 23:46:59 -0400
Subject: [PATCH 7/7] whitespace

---
 libcxx/include/optional                                          | 1 -
 .../std/utilities/optional/optional.monadic/and_then.pass.cpp    | 1 -
 .../std/utilities/optional/optional.monadic/or_else.pass.cpp     | 1 -
 .../std/utilities/optional/optional.monadic/transform.pass.cpp   | 1 -
 4 files changed, 4 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index ed333a17246ab..3a8191a3d1971 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -768,7 +768,6 @@ inline constexpr bool __is_constructible_for_optional_initializer_list_v =
 #    if _LIBCPP_STD_VER >= 26
 template <class _Tp, class... _Args>
 inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Args...> = false;
-
 template <class _Tp, class _Arg>
 inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Arg> =
     is_constructible_v<_Tp&, _Arg> && !reference_constructs_from_temporary_v<_Tp&, _Arg>;
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
index ee38e2fd9e54a..93bbd74cd8678 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
@@ -339,7 +339,6 @@ constexpr bool test_ref() {
       assert(std::move(i).and_then(std::move(nl)) == std::nullopt);
     }
   }
-
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
index 2e7e9737803a4..326013cd6557f 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
@@ -15,7 +15,6 @@
 #include "MoveOnly.h"
 
 #include <cassert>
-#include <concepts>
 #include <optional>
 
 struct NonMovable {
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index ca7c6d9bbdc4e..b8536b790f749 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -308,7 +308,6 @@ constexpr bool test_ref() {
     auto o6r               = o6.transform([](int) { return 42; });
     assert(!o6r);
   }
-
   return true;
 }
 #endif



More information about the libcxx-commits mailing list