[libcxx-commits] [libcxx] 48ae4d3 - [libc++] Fix `optional<T>::transform` into `optional<T&>` (#221506)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 9 03:43:56 PDT 2026


Author: William Tran-Viet
Date: 2026-09-09T18:43:51+08:00
New Revision: 48ae4d3b158042b4ad77a6b23aa412aedac7105a

URL: https://github.com/llvm/llvm-project/commit/48ae4d3b158042b4ad77a6b23aa412aedac7105a
DIFF: https://github.com/llvm/llvm-project/commit/48ae4d3b158042b4ad77a6b23aa412aedac7105a.diff

LOG: [libc++] Fix `optional<T>::transform` into `optional<T&>` (#221506)

Resolves #220332

- Make `optional<T>` a friend of `optional<T&>`, and add tests.

Added: 
    

Modified: 
    libcxx/include/__optional/optional_ref.h
    libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index e76bb9a75845d..995b122cecdda 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -77,6 +77,9 @@ class optional<_Tp&> : public __optional_ref_iterator_base<_Tp&> {
   static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
 
 private:
+  template <class>
+  friend class optional;
+
   _Tp* __value_ = nullptr;
 
   template <class _Up>

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..a1109fb3f2be8 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -321,6 +321,39 @@ constexpr bool test_ref() {
     assert(&(*o2) == &j);
   }
 
+  // optional<T> -> optional<T&>, https://llvm.org/PR220332
+  { // &, &&
+    int i = 42;
+    int j = 43;
+    int k = 44;
+
+    std::optional<int> opt{i};
+
+    std::same_as<std::optional<int&>> decltype(auto) o = opt.transform([&](auto) -> int& { return j; });
+    assert(o == 43);
+    assert(&(*o) == &j);
+
+    std::same_as<std::optional<int&>> decltype(auto) o2 = std::move(opt).transform([&](auto) -> int& { return k; });
+    assert(o2 == 44);
+    assert(&(*o2) == &k);
+  }
+
+  { // const&, const&&
+    int i = 42;
+    int j = 43;
+    int k = 44;
+
+    const std::optional<int> opt{i};
+
+    std::same_as<std::optional<int&>> decltype(auto) o = opt.transform([&](auto) -> int& { return j; });
+    assert(o == 43);
+    assert(&(*o) == &j);
+
+    std::same_as<std::optional<int&>> decltype(auto) o2 = std::move(opt).transform([&](auto) -> int& { return k; });
+    assert(o2 == 44);
+    assert(&(*o2) == &k);
+  }
+
   return true;
 }
 #endif


        


More information about the libcxx-commits mailing list