[libcxx-commits] [libcxx] 4c9d1bd - [libc++] Implement P3836R2: Make `optional<T&>` trivially copyable (#171528)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 23 23:44:36 PST 2025


Author: William Tran-Viet
Date: 2025-12-24T15:44:32+08:00
New Revision: 4c9d1bdf9400be76f8937c9d80df706d2a3680ae

URL: https://github.com/llvm/llvm-project/commit/4c9d1bdf9400be76f8937c9d80df706d2a3680ae
DIFF: https://github.com/llvm/llvm-project/commit/4c9d1bdf9400be76f8937c9d80df706d2a3680ae.diff

LOG: [libc++] Implement P3836R2: Make `optional<T&>` trivially copyable (#171528)

Resolves #171275

- `*_assign_base` base class trivial overloads needed to be updated to
allow references.
- Add tests
- Update release notes

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes/22.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/optional
    libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 82271be7a22ab..012a0c28ec18f 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -52,6 +52,7 @@ Implemented Papers
 - P2944R3: Comparisons for ``reference_wrapper`` (`Github <https://llvm.org/PR105424>`__)
 - P3168R2: Give ``std::optional`` Range Support (`Github <https://llvm.org/PR105430>`__)
 - P3567R2: ``flat_meow`` Fixes (`Github <https://llvm.org/PR162022>`__)
+- P3836R2: Make ``optional<T&>`` trivially copyable (`Github <https://llvm.org/PR171275>`__)
 
 Improvements and New Features
 -----------------------------

diff  --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 3687e3dac2a8f..6a77ec83b61b8 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -162,7 +162,7 @@
 "`P3567R2 <https://wg21.link/P3567R2>`__","``flat_meow`` Fixes","2025-11 (Kona)","|Complete|","22","`#171272 <https://github.com/llvm/llvm-project/issues/171272>`__",""
 "`P3663R3 <https://wg21.link/P3663R3>`__","Future-proof ``submdspan_mapping``","2025-11 (Kona)","","","`#166089 <https://github.com/llvm/llvm-project/issues/166089>`__",""
 "`P3914R0 <https://wg21.link/P3914R0>`__","Assorted NB comment resolutions for Kona 2025","2025-11 (Kona)","","","`#171274 <https://github.com/llvm/llvm-project/issues/171274>`__",""
-"`P3836R2 <https://wg21.link/P3836R2>`__","Make ``optional<T&>`` trivially copyable","2025-11 (Kona)","","","`#171275 <https://github.com/llvm/llvm-project/issues/171275>`__",""
+"`P3836R2 <https://wg21.link/P3836R2>`__","Make ``optional<T&>`` trivially copyable","2025-11 (Kona)","|Complete|","22","`#171275 <https://github.com/llvm/llvm-project/issues/171275>`__",""
 "`P3860R1 <https://wg21.link/P3860R1>`__","Proposed Resolution for NB Comment GB13-309 ``atomic_ref<T>`` is not convertible to ``atomic_ref<const T>``","2025-11 (Kona)","","","`#171276 <https://github.com/llvm/llvm-project/issues/171276>`__",""
 "`P3388R3 <https://wg21.link/P3388R3>`__","When Do You Know ``connect`` Doesn’t Throw?","2025-11 (Kona)","","","`#171277 <https://github.com/llvm/llvm-project/issues/171277>`__",""
 "`P3774R1 <https://wg21.link/P3774R1>`__","Rename ``std::nontype``, and make it broadly useful","2025-11 (Kona)","","","`#171279 <https://github.com/llvm/llvm-project/issues/171279>`__",""

diff  --git a/libcxx/include/optional b/libcxx/include/optional
index 95b7d548f2560..440fdf73a4310 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -549,7 +549,7 @@ struct __optional_storage_base<_Tp, true> {
   }
 };
 
-template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
+template <class _Tp, bool = is_trivially_copy_constructible_v<_Tp> || is_lvalue_reference_v<_Tp>>
 struct __optional_copy_base : __optional_storage_base<_Tp> {
   using __optional_storage_base<_Tp>::__optional_storage_base;
 };
@@ -569,7 +569,7 @@ struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
   _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&)      = default;
 };
 
-template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
+template <class _Tp, bool = is_trivially_move_constructible_v<_Tp> || is_lvalue_reference_v<_Tp>>
 struct __optional_move_base : __optional_copy_base<_Tp> {
   using __optional_copy_base<_Tp>::__optional_copy_base;
 };
@@ -592,8 +592,9 @@ struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
 };
 
 template <class _Tp,
-          bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value &&
-                 is_trivially_copy_assignable<_Tp>::value>
+          bool = (is_trivially_destructible_v<_Tp> && is_trivially_copy_constructible_v<_Tp> &&
+                  is_trivially_copy_assignable_v<_Tp>) ||
+                 is_lvalue_reference_v<_Tp>>
 struct __optional_copy_assign_base : __optional_move_base<_Tp> {
   using __optional_move_base<_Tp>::__optional_move_base;
 };
@@ -616,8 +617,9 @@ struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
 };
 
 template <class _Tp,
-          bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value &&
-                 is_trivially_move_assignable<_Tp>::value>
+          bool = (is_trivially_destructible_v<_Tp> && is_trivially_move_constructible_v<_Tp> &&
+                  is_trivially_move_assignable_v<_Tp>) ||
+                 is_lvalue_reference_v<_Tp>>
 struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
   using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
 };
@@ -646,8 +648,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<_Tp>::value && is_copy_assignable<_Tp>::value),
-                          (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >;
+    __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>>;
 
 template <class _Tp>
 class optional;

diff  --git a/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp
index fe760e60cb951..159abcb61f976 100644
--- a/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/triviality.pass.cpp
@@ -17,7 +17,8 @@
 // constexpr optional(optional&& rhs) noexcept(see below);
 // constexpr optional<T>& operator=(const optional& rhs);
 // constexpr optional<T>& operator=(optional&& rhs) noexcept(see below);
-
+//
+// Also test that std::optional<T&> is always trivially copyable.
 
 #include <optional>
 #include <type_traits>
@@ -62,6 +63,19 @@ struct SpecialMemberTest {
         "trivially move constructible, "
         "trivially move assignable, and"
         "trivially destructible.");
+
+#if TEST_STD_VER >= 26
+    static_assert(std::is_trivially_copyable_v<std::optional<T&>>);
+    static_assert(std::is_trivially_copy_constructible_v<std::optional<T&>>);
+    static_assert(std::is_trivially_move_constructible_v<std::optional<T&>>);
+    static_assert(std::is_trivially_constructible_v<std::optional<T&>, std::optional<T&>&>);
+    static_assert(std::is_trivially_constructible_v<std::optional<T&>, const std::optional<T&>&&>);
+    static_assert(std::is_trivially_copy_assignable_v<std::optional<T&>>);
+    static_assert(std::is_trivially_move_assignable_v<std::optional<T&>>);
+    static_assert(std::is_trivially_assignable_v<std::optional<T&>&, std::optional<T&>&>);
+    static_assert(std::is_trivially_assignable_v<std::optional<T&>&, const std::optional<T&>&&>);
+    static_assert(std::is_trivially_destructible_v<std::optional<T&>>);
+#endif
 };
 
 template <class ...Args> static void sink(Args&&...) {}


        


More information about the libcxx-commits mailing list