[libcxx-commits] [libcxx] [libc++] Fix `optional<T>::transform` into `optional<T&>` (PR #221506)
William Tran-Viet via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Sep 5 17:38:59 PDT 2026
https://github.com/smallp-o-p created https://github.com/llvm/llvm-project/pull/221506
Resolves #220332
- Make `optional<T>` a friend of `optional<T&>`, and add tests.
>From 4b16af031c35bd8686cb2a8786f5c18c9e5f00a8 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 5 Sep 2026 20:34:57 -0400
Subject: [PATCH] Fix optional<T>::transform into optional<T&> transform by
making optional a friend of optional<T&>
---
libcxx/include/__optional/optional_ref.h | 3 ++
.../optional.monadic/transform.pass.cpp | 33 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index 2fa8c474212e7..802da17f65c53 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -78,6 +78,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..67cd4ba9bea76 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&> GH #220332
+ { // &, &&
+ 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