[libcxx-commits] [libcxx] [libc++] Add `optional<T&>(optional<U>...)` constraints for ctors shared with `optional<T>` (PR #195759)

William Tran-Viet via libcxx-commits libcxx-commits at lists.llvm.org
Mon May 4 16:48:48 PDT 2026


https://github.com/smallp-o-p created https://github.com/llvm/llvm-project/pull/195759

- Constraints were missing for some `optional<U>` constructors that were shared with `optional<T>`:
  - `const optional<U>&`
  - `optional<U>&&`
- Add some tests to verify the `is_constructible<...>` parts of the constraints for all four `optional<U>` constructors.
- As per the LLVM AI policy: Tests were created with assistance of AI. 

>From 3b3cf22409bb2e764a9daf1fd147c91d0720e65d Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 4 May 2026 18:40:31 -0400
Subject: [PATCH 1/2] Constraints for optional<T&> optional<U> ctors shared
 with optional<T>

---
 libcxx/include/optional | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index f7e12f84beba0..ec36cd57412aa 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -953,11 +953,35 @@ private:
     }
   };
 
+  template <class _QualUp>
+  struct _CheckOptionalLikeRefConstructor {
+    template <class>
+    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
+      return !is_convertible_v<_QualUp, _Tp&>;
+    }
+
+    template <class>
+    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
+      return is_convertible_v<_QualUp, _Tp&>;
+    }
+
+    template <class>
+    _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_assign() {
+      return false;
+    }
+  };
+
   template <class _Up, class _QualUp>
   using _CheckOptionalLikeCtor _LIBCPP_NODEBUG =
-      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
-           _CheckOptionalLikeConstructor<_QualUp>,
-           __check_tuple_constructor_fail >;
+      _If<_And<is_lvalue_reference<_Tp>, // optional<T&>
+               _IsNotSame<__remove_cvref_t<_Tp>, optional<_Up>>,
+               _IsNotSame<_Tp&, _Up>,
+               is_constructible<_Tp&, _QualUp>>::value,
+          _CheckOptionalLikeRefConstructor<_QualUp>,
+          _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value, // optional<T>
+               _CheckOptionalLikeConstructor<_QualUp>,
+               __check_tuple_constructor_fail > >;
+
   template <class _Up, class _QualUp>
   using _CheckOptionalLikeAssign _LIBCPP_NODEBUG =
       _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,

>From 3151f1540eb5de908bce640dbc5b54e791ed9fb2 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 4 May 2026 19:42:12 -0400
Subject: [PATCH 2/2] Some best-effort tests [AI-assisted]

---
 .../const_optional_U.pass.cpp                    | 12 ++++++++++++
 .../optional.object.ctor/optional_U.pass.cpp     |  9 +++++++++
 .../optional.object/optional_helper_types.h      | 16 ++++++++++++++++
 3 files changed, 37 insertions(+)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index 844317c8570d9..0961fb21effd6 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -182,6 +182,18 @@ constexpr bool test_ref() {
 
   static_assert(!std::is_constructible_v<std::optional<int>, const std::optional<ConstRValueOnly<int>>&&>);
 
+  // optional(const optional<U>&) !is_constructible_v<T&, const U&>.
+  static_assert(std::is_constructible_v<std::optional<int&>, const std::optional<ConstLValueOnly<int>>&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, const std::optional<LValueOnly<int>>&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, const std::optional<RValueOnly<int>>&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, const std::optional<ConstRValueOnly<int>>&>);
+
+  // optional(const optional<U>&&) !is_constructible_v<T&, const U>.
+  static_assert(std::is_constructible_v<std::optional<int&>, const std::optional<ConstLValueOnly<int>>&&>);
+  static_assert(std::is_constructible_v<std::optional<int&>, const std::optional<ConstRValueOnly<int>>&&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, const std::optional<LValueOnly<int>>&&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, const std::optional<RValueOnly<int>>&&>);
+
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 03082033cd4dc..a5d1c50494a75 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -174,6 +174,15 @@ constexpr bool test_ref() {
     ASSERT_NOT_NOEXCEPT(std::optional<const int&>(std::move(o1)));
   }
 
+  // optional(optional<U>&) !is_constructible_v<T&, U&>.
+  static_assert(std::is_constructible_v<std::optional<int&>, std::optional<LValueOnly<int>>&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, std::optional<RValueOnly<int>>&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, std::optional<ConstRValueOnly<int>>&>);
+
+  // optional(optional<U>&&) !is_constructible_v<T&, U>.
+  static_assert(std::is_constructible_v<std::optional<int&>, std::optional<RValueOnly<int>>&&>);
+  static_assert(!std::is_constructible_v<std::optional<int&>, std::optional<LValueOnly<int>>&&>);
+
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h b/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h
index d9b17a0b91f3b..cf7e12992d224 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h
+++ b/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h
@@ -78,6 +78,22 @@ struct LValueOnly {
   constexpr operator T&() const&& = delete;
 };
 
+template <typename T>
+struct ConstLValueOnly {
+  operator T&() & = delete;
+  operator T&() const&;
+  operator T&() &&      = delete;
+  operator T&() const&& = delete;
+};
+
+template <typename T>
+struct RValueOnly {
+  operator T&() &      = delete;
+  operator T&() const& = delete;
+  operator T&() &&;
+  operator T&() const&& = delete;
+};
+
 template <typename T>
 struct ConstRValueOnly {
   mutable T val{};



More information about the libcxx-commits mailing list