[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