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

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 5 18:57:52 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>

- Break out the optional<T&> implementation that was interwoven with the regular interface
- This should the implementation
- Also fixes a bug where returning an optional<T&> for the monadic functions was broken

---

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


6 Files Affected:

- (modified) libcxx/include/optional (+175-180) 
- (modified) libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp (+35-2) 
- (modified) libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp (+8) 
- (modified) libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp (+17-4) 
- (modified) libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.verify.cpp (+7-1) 
- (modified) libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.verify.cpp (+8-3) 


``````````diff
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_construc...
[truncated]

``````````

</details>


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


More information about the libcxx-commits mailing list