[libcxx-commits] [libcxx] [libc++] P3612R1: Harmonize proxy-reference operations (PR #173710)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Dec 27 01:11:09 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

<details>
<summary>Changes</summary>

Implements it as a Defect Report against C++03 except for the deprecation.

Fixes #<!-- -->171281.

---

Patch is 23.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173710.diff


11 Files Affected:

- (modified) libcxx/docs/ReleaseNotes/22.rst (+1) 
- (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1) 
- (modified) libcxx/include/__bit_reference (+17-30) 
- (modified) libcxx/include/__vector/vector_bool.h (+5-2) 
- (modified) libcxx/include/bitset (+11-8) 
- (modified) libcxx/include/vector (+10-5) 
- (added) libcxx/test/std/containers/sequences/vector.bool/reference.swap.deprecated.verify.cpp (+37) 
- (modified) libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp (+2) 
- (modified) libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp (+121-16) 
- (modified) libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp (+43-25) 
- (added) libcxx/test/std/utilities/template.bitset/bitset.members/reference.swap.pass.cpp (+111) 


``````````diff
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 0d1a1fbc00f2c..8883ae5e48be7 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>`__)
+- P3612R1: Harmonize proxy-reference operations (LWG 3638 and 4187) (`Github <https://llvm.org/PR171281>`__)
 - P3836R2: Make ``optional<T&>`` trivially copyable (`Github <https://llvm.org/PR171275>`__)
 - P1789R3: Library Support for Expansion Statements (`Github <https://llvm.org/PR167184>`__)
 
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 9bb5d2bda3d4d..9c398139ff7a1 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -167,7 +167,7 @@
 "`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>`__",""
 "`P3819R0 <https://wg21.link/P3819R0>`__","Remove ``evaluation_exception()`` from contract-violation handling for C++26","2025-11 (Kona)","","","`#171280 <https://github.com/llvm/llvm-project/issues/171280>`__",""
-"`P3612R1 <https://wg21.link/P3612R1>`__","Harmonize proxy-reference operations (LWG 3638 and 4187)","2025-11 (Kona)","","","`#171281 <https://github.com/llvm/llvm-project/issues/171281>`__",""
+"`P3612R1 <https://wg21.link/P3612R1>`__","Harmonize proxy-reference operations (LWG 3638 and 4187)","2025-11 (Kona)","|Complete|","22","`#171281 <https://github.com/llvm/llvm-project/issues/171281>`__","Implemented as a DR against C++03 except for the deprecation."
 "`P3778R0 <https://wg21.link/P3778R0>`__","Fix for ``type_order`` template definition","2025-11 (Kona)","","","`#171284 <https://github.com/llvm/llvm-project/issues/171284>`__",""
 "`P1789R3 <https://wg21.link/P1789R3>`__","Library Support for Expansion Statements","2025-11 (Kona)","|Complete|","22","`#167268 <https://github.com/llvm/llvm-project/issues/167268>`__",""
 "`P3922R1 <https://wg21.link/P3922R1>`__","Missing deduction guide from ``simd::mask`` to ``simd::vec``","2025-11 (Kona)","","","`#171285 <https://github.com/llvm/llvm-project/issues/171285>`__",""
diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index 8daf3a2baafcd..f80ce9fcf8ea6 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -170,6 +170,23 @@ public:
     return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__countr_zero(__mask_)));
   }
 
+  _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+  swap(__bit_reference __x, __bit_reference __y) _NOEXCEPT {
+    bool __t = __x;
+    __x      = __y;
+    __y      = __t;
+  }
+  _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(__bit_reference __x, bool& __y) _NOEXCEPT {
+    bool __t = __x;
+    __x      = __y;
+    __y      = __t;
+  }
+  _LIBCPP_HIDE_FROM_ABI friend _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, __bit_reference __y) _NOEXCEPT {
+    bool __t = __x;
+    __x      = __y;
+    __y      = __t;
+  }
+
 private:
   _LIBCPP_HIDE_FROM_ABI
   _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
@@ -180,36 +197,6 @@ private:
 template <class _Cp>
 class __bit_reference<_Cp, false> {};
 
-template <class _Cp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT {
-  bool __t = __x;
-  __x      = __y;
-  __y      = __t;
-}
-
-template <class _Cp, class _Dp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT {
-  bool __t = __x;
-  __x      = __y;
-  __y      = __t;
-}
-
-template <class _Cp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT {
-  bool __t = __x;
-  __x      = __y;
-  __y      = __t;
-}
-
-template <class _Cp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT {
-  bool __t = __x;
-  __x      = __y;
-  __y      = __t;
-}
-
 template <class _Cp>
 class __bit_const_reference {
   using __storage_type _LIBCPP_NODEBUG    = typename _Cp::__storage_type;
diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h
index f81fcd92a7e49..0483db569df46 100644
--- a/libcxx/include/__vector/vector_bool.h
+++ b/libcxx/include/__vector/vector_bool.h
@@ -398,8 +398,11 @@ class vector<bool, _Allocator> {
 #else
       _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
 #endif
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void swap(reference __x, reference __y) _NOEXCEPT {
-    std::swap(__x, __y);
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX26
+      _LIBCPP_CONSTEXPR_SINCE_CXX20 static void swap(reference __x, reference __y) _NOEXCEPT {
+    bool __t = __x;
+    __x      = __y;
+    __y      = __t;
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __sz, value_type __x = false);
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 37253f5722389..c7e56ced1c41f 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -27,15 +27,18 @@ public:
     // bit reference:
     class reference
     {
-        friend class bitset;
-        reference() noexcept;
     public:
-        ~reference() noexcept;
-        reference& operator=(bool x) noexcept;           // for b[i] = x;
-        reference& operator=(const reference&) noexcept; // for b[i] = b[j];
-        bool operator~() const noexcept;                 // flips the bit
-        operator bool() const noexcept;                  // for x = b[i];
-        reference& flip() noexcept;                      // for b[i].flip();
+        reference(const reference& x) noexcept;                 // constexpr since C++23
+        ~reference() noexcept;                                  // constexpr since C++23
+        reference& operator=(bool x) noexcept;                  // constexpr since C++23; for b[i] = x;
+        reference& operator=(const reference&) noexcept;        // constexpr since C++23; for b[i] = b[j];
+        constexpr reference& operator=(bool x) const noexcept;  // since C++23
+        bool operator~() const noexcept;                        // constexpr since C++23; flips the bit
+        operator bool() const noexcept;                         // constexpr since C++23; for x = b[i];
+        void flip() noexcept;                                   // constexpr since C++23; for b[i].flip();
+        friend void swap(reference x, reference y) noexcept;    // constexpr since C++23
+        friend void swap(reference x, bool& y) noexcept;        // constexpr since C++23
+        friend void swap(bool& x, reference y) noexcept;        // constexpr since C++23
     };
 
     // 23.3.5.1 constructors:
diff --git a/libcxx/include/vector b/libcxx/include/vector
index d2d5fcf4a3199..37b75f1619e53 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -152,12 +152,16 @@ public:
     class reference
     {
     public:
-        reference(const reference&) noexcept;
-        operator bool() const noexcept;
-        reference& operator=(bool x) noexcept;
-        reference& operator=(const reference& x) noexcept;
+        reference(const reference&) noexcept;                  // constexpr since C++20
+        operator bool() const noexcept;                        // constexpr since C++20
+        reference& operator=(bool x) noexcept;                 // constexpr since C++20
+        reference& operator=(const reference& x) noexcept;     // constexpr since C++20
+        constexpr reference& operator=(bool x) const noexcept; // since C++23
         iterator operator&() const noexcept;
-        void flip() noexcept;
+        void flip() noexcept;                                  // constexpr since C++20
+        friend void swap(reference x, reference y) noexcept;   // constexpr since C++20
+        friend void swap(reference x, bool& y) noexcept;       // constexpr since C++20
+        friend void swap(bool& x, reference y) noexcept;       // constexpr since C++20
     };
 
     class const_reference
@@ -255,6 +259,7 @@ public:
     void swap(vector&)
         noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
                  allocator_traits<allocator_type>::is_always_equal::value);  // C++17
+    static void swap(reference x, reference, y) noexcept;                    // deprecated in C++26
     void flip() noexcept;
 
     bool __invariants() const;
diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference.swap.deprecated.verify.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.deprecated.verify.cpp
new file mode 100644
index 0000000000000..b8259c63b954b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.deprecated.verify.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <vector>
+
+// vector<bool>;
+// static void swap(reference x, reference y) noexcept; // deprecated in C++26
+
+#include <vector>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+void test() {
+  {
+    using VB = std::vector<bool>;
+    VB vb(2);
+    VB::swap(vb[0], vb[1]); // expected-warning {{'swap' is deprecated}}
+  }
+  {
+    using VB = std::vector<bool, min_allocator<bool>>;
+    VB vb(2);
+    VB::swap(vb[0], vb[1]); // expected-warning {{'swap' is deprecated}}
+  }
+  {
+    using VB = std::pmr::vector<bool>;
+    VB vb(2);
+    VB::swap(vb[0], vb[1]); // expected-warning {{'swap' is deprecated}}
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp
index a0476b6fc305b..875c5224e833b 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/reference.swap.pass.cpp
@@ -11,6 +11,8 @@
 
 // static void swap(reference x, reference y) noexcept;
 
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+
 #include <vector>
 #include <cassert>
 
diff --git a/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp
index 9b29a245e389a..132c82c54903d 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/swap.pass.cpp
@@ -11,14 +11,49 @@
 
 // void swap(vector& x);
 
+// class reference;
+// friend void swap(reference x, reference y);
+// friend void swap(reference x, bool&);
+// friend void swap(bool& x, reference y);
+
+// XFAIL: FROZEN-CXX03-HEADERS-FIXME
+
 #include <vector>
 #include <cassert>
+#include <type_traits>
+#include <utility>
+
 #include "test_macros.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
 
-TEST_CONSTEXPR_CXX20 bool tests() {
+template <class T, class U, class = void>
+struct can_qualified_std_swap_with : std::false_type {};
+template <class T, class U>
+struct can_qualified_std_swap_with<T, U, decltype((void)std::swap(std::declval<T>(), std::declval<U>()))>
+    : std::true_type {};
+
+template <class T>
+struct can_qualified_std_swap : can_qualified_std_swap_with<T&, T&>::type {};
+
+namespace adl_only {
+void swap();
+
+template <class T, class U, class = void>
+struct can_swap_with : std::false_type {};
+template <class T, class U>
+struct can_swap_with<T, U, decltype((void)swap(std::declval<T>(), std::declval<U>()))> : std::true_type {};
+
+template <class T>
+struct can_swap : can_swap_with<T&, T&>::type {};
+} // namespace adl_only
+
+TEST_CONSTEXPR_CXX20 void test_vector_bool_swap() {
   {
+    typedef std::vector<bool> VB;
+    static_assert(can_qualified_std_swap<VB>::value, "");
+    static_assert(adl_only::can_swap<VB>::value, "");
+
     std::vector<bool> v1(100);
     std::vector<bool> v2(200);
     v1.swap(v2);
@@ -29,6 +64,10 @@ TEST_CONSTEXPR_CXX20 bool tests() {
   }
   {
     typedef test_allocator<bool> A;
+    typedef std::vector<bool, A> VB;
+    static_assert(can_qualified_std_swap<VB>::value, "");
+    static_assert(adl_only::can_swap<VB>::value, "");
+
     std::vector<bool, A> v1(100, true, A(1, 1));
     std::vector<bool, A> v2(200, false, A(1, 2));
     swap(v1, v2);
@@ -41,6 +80,10 @@ TEST_CONSTEXPR_CXX20 bool tests() {
   }
   {
     typedef other_allocator<bool> A;
+    typedef std::vector<bool, A> VB;
+    static_assert(can_qualified_std_swap<VB>::value, "");
+    static_assert(adl_only::can_swap<VB>::value, "");
+
     std::vector<bool, A> v1(100, true, A(1));
     std::vector<bool, A> v2(200, false, A(2));
     swap(v1, v2);
@@ -51,18 +94,13 @@ TEST_CONSTEXPR_CXX20 bool tests() {
     assert(v1.get_allocator() == A(2));
     assert(v2.get_allocator() == A(1));
   }
-  {
-    std::vector<bool> v(2);
-    std::vector<bool>::reference r1 = v[0];
-    std::vector<bool>::reference r2 = v[1];
-    r1                              = true;
-    using std::swap;
-    swap(r1, r2);
-    assert(v[0] == false);
-    assert(v[1] == true);
-  }
 #if TEST_STD_VER >= 11
   {
+    using A  = min_allocator<bool>;
+    using VB = std::vector<bool, A>;
+    static_assert(can_qualified_std_swap<VB>::value, "");
+    static_assert(adl_only::can_swap<VB>::value, "");
+
     std::vector<bool, min_allocator<bool>> v1(100);
     std::vector<bool, min_allocator<bool>> v2(200);
     v1.swap(v2);
@@ -72,7 +110,7 @@ TEST_CONSTEXPR_CXX20 bool tests() {
     assert(v2.capacity() >= 100);
   }
   {
-    typedef min_allocator<bool> A;
+    using A = min_allocator<bool>;
     std::vector<bool, A> v1(100, true, A());
     std::vector<bool, A> v2(200, false, A());
     swap(v1, v2);
@@ -83,18 +121,85 @@ TEST_CONSTEXPR_CXX20 bool tests() {
     assert(v1.get_allocator() == A());
     assert(v2.get_allocator() == A());
   }
+#endif
+}
+
+TEST_CONSTEXPR_CXX20 void test_vector_bool_reference_swap() {
+  { // Test that only homogeneous vector<bool, A>::reference swap is supported.
+    typedef std::vector<bool>::reference VBRef1;
+    typedef std::vector<bool, test_allocator<bool> >::reference VBRef2;
+    static_assert(can_qualified_std_swap_with<VBRef1, VBRef2>::value == std::is_same<VBRef1, VBRef2>::value, "");
+    static_assert(adl_only::can_swap_with<VBRef1, VBRef2>::value == std::is_same<VBRef1, VBRef2>::value, "");
+  }
   {
-    std::vector<bool, min_allocator<bool>> v(2);
-    std::vector<bool, min_allocator<bool>>::reference r1 = v[0];
-    std::vector<bool, min_allocator<bool>>::reference r2 = v[1];
-    r1                                                   = true;
+    typedef std::vector<bool>::reference VBRef;
+    static_assert(can_qualified_std_swap<VBRef>::value, "");
+    static_assert(!can_qualified_std_swap_with<VBRef, VBRef>::value, "");
+    static_assert(!can_qualified_std_swap_with<VBRef, bool&>::value, "");
+    static_assert(!can_qualified_std_swap_with<bool&, VBRef>::value, "");
+    static_assert(adl_only::can_swap<VBRef>::value, "");
+    static_assert(adl_only::can_swap_with<VBRef, VBRef>::value, "");
+    static_assert(adl_only::can_swap_with<VBRef, bool&>::value, "");
+    static_assert(adl_only::can_swap_with<bool&, VBRef>::value, "");
+
+    using std::swap;
+
+    std::vector<bool> v(2);
+    VBRef r1 = v[0];
+    VBRef r2 = v[1];
+    r1       = true;
+
+    swap(r1, r2);
+    assert(v[0] == false);
+    assert(v[1] == true);
+
+    bool b1 = true;
+    swap(r1, b1);
+    assert(v[0] == true);
+    assert(b1 == false);
+
+    swap(b1, r1);
+    assert(v[0] == false);
+    assert(b1 == true);
+  }
+#if TEST_STD_VER >= 11
+  {
+    using VBRef = std::vector<bool, min_allocator<bool>>::reference;
+    static_assert(can_qualified_std_swap<VBRef>::value, "");
+    static_assert(!can_qualified_std_swap_with<VBRef, VBRef>::value, "");
+    static_assert(!can_qualified_std_swap_with<VBRef, bool&>::value, "");
+    static_assert(!can_qualified_std_swap_with<bool&, VBRef>::value, "");
+    static_assert(adl_only::can_swap<VBRef>::value, "");
+    static_assert(adl_only::can_swap_with<VBRef, VBRef>::value, "");
+    static_assert(adl_only::can_swap_with<VBRef, bool&>::value, "");
+    static_assert(adl_only::can_swap_with<bool&, VBRef>::value, "");
+
     using std::swap;
+
+    std::vector<bool, min_allocator<bool>> v(2);
+    VBRef r1 = v[0];
+    VBRef r2 = v[1];
+    r1       = true;
+
     swap(r1, r2);
     assert(v[0] == false);
     assert(v[1] == true);
+
+    bool b1 = true;
+    swap(r1, b1);
+    assert(v[0] == true);
+    assert(b1 == false);
+
+    swap(b1, r1);
+    assert(v[0] == false);
+    assert(b1 == true);
   }
 #endif
+}
 
+TEST_CONSTEXPR_CXX20 bool tests() {
+  test_vector_bool_swap();
+  test_vector_bool_reference_swap();
   return true;
 }
 
diff --git a/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp
index 8d3aeca7da3c6..34ea2ac0a4496 100644
--- a/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp
+++ b/libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp
@@ -12,38 +12,56 @@
 #include <cassert>
 #include <cstddef>
 #include <vector>
+#include <type_traits>
 
 #include "../bitset_test_cases.h"
 #include "test_macros.h"
 
 template <std::size_t N>
 TEST_CONSTEXPR_CXX23 void test_index() {
-    std::vector<std::bitset<N> > const cases = get_test_cases<N>();
-    for (std::size_t c = 0; c != cases.size(); ++c) {
-        std::bitset<N> v1 = cases[c];
-        if (v1.size() > 0) {
-            assert(v1[N/2] == v1.test(N/2));
-            typename std::bitset<N>::reference r = v1[N/2];
-            assert(r == v1.test(N/2));
-            typename std::bitset<N>::reference r2 = v1[N/2];
-            r = r2;
-            assert(r == v1.test(N/2));
-            r = false;
-            assert(r == false);
-            assert(v1.test(N/2) == false);
-            r = true;
-            assert(r == true);
-            assert(v1.test(N/2) == true);
-            bool b = ~r;
-            assert(r == true);
-            assert(v1.test(N/2) == true);
-            assert(b == false);
-            r.flip();
-            assert(r == false);
-            assert(v1.test(N/2) == false);
-        }
-        ASSERT_SAME_TYPE(decltype(v1[0]), typename std::bitset<N>::reference);
+  typedef typename std::bitset<N>::reference BRef;
+#if TEST_STD_VER >= 23
+  static_assert(std::is_assignable_v<const BRef, bool>);
+#else
+  static_assert(!std::is_assignable<const BRef, bool>::value, "");
+#endif
+
+  std::vector<std::bitset<N> > const cases = get_test_cases<N>();
+  for (std::size_t c = 0; c != cases.size(); ++c) {
+    std::bitset<N> v1 = cases[c];
+    if (v1.size() > 0) {
+      assert(v1[N / 2] == v1.test(N / 2));
+      BRef r = v1[N / 2];
+      assert(r == v1.test(N / 2));
+      BRef r2 = v1[N / 2];
+      r       = r2;
+      assert(r == v1.test(N / 2));
+      r = false;
+      assert(r == false);
+      assert(v1.test(N / 2) == false);
+      r = true;
+      assert(r == true);
+      assert(v1.test(N / 2) == true);
+      bool b = ~r;
+      assert(r == true);
+      assert(v1.test(N / 2) == true);
+      assert(b == false);
+      r.flip();
+      assert(r == false);
+      assert(v1.test(N / 2) == false);
+
+#if TEST_STD_VER >= 23
+      const auto& cr     = r;
+      decltype(auto) cr2 = (cr = true);
+      ASSERT_SAME_TYPE(decltype(cr2), const BRef&);
+   ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/173710


More information about the libcxx-commits mailing list