[libcxx-commits] [libcxx] 737a450 - Add constexpr to pair

Michael Schellenberger Costa via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 2 12:22:08 PDT 2020


Author: Michael Schellenberger Costa
Date: 2020-09-02T21:21:24+02:00
New Revision: 737a4501e815d8dd57e5095dbbbede500dfa8ccb

URL: https://github.com/llvm/llvm-project/commit/737a4501e815d8dd57e5095dbbbede500dfa8ccb
DIFF: https://github.com/llvm/llvm-project/commit/737a4501e815d8dd57e5095dbbbede500dfa8ccb.diff

LOG: Add constexpr to pair

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D80558

Added: 
    

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/tuple
    libcxx/include/utility
    libcxx/include/version
    libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp
    libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a6867fb30a37..1dbeb213f8ba 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -184,6 +184,8 @@ Status
     ------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_swap_algorithms``           *unimplemented*  
     ------------------------------------------------- -----------------
+    ``__cpp_lib_constexpr_utility ``                  ``201811L``      
+    ------------------------------------------------- -----------------
     ``__cpp_lib_destroying_delete``                   ``201806L``      
     ------------------------------------------------- -----------------
     ``__cpp_lib_endian``                              ``201907L``      

diff  --git a/libcxx/include/tuple b/libcxx/include/tuple
index 1f80b70759c7..c3c7db5ff118 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1393,7 +1393,7 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator<tuple<_Tp...>, _Alloc>
 
 template <class _T1, class _T2>
 template <class... _Args1, class... _Args2, size_t ..._I1, size_t ..._I2>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 pair<_T1, _T2>::pair(piecewise_construct_t,
                      tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
                      __tuple_indices<_I1...>, __tuple_indices<_I2...>)

diff  --git a/libcxx/include/utility b/libcxx/include/utility
index 7ac322bfe710..13489de22c95 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -499,7 +499,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
           second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {}
 
     template <class... _Args1, class... _Args2>
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pair(piecewise_construct_t __pc,
          tuple<_Args1...> __first_args, tuple<_Args2...> __second_args)
         _NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value &&
@@ -508,7 +508,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
                 typename __make_tuple_indices<sizeof...(_Args1)>::type(),
                 typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pair& operator=(typename conditional<
                         is_copy_assignable<first_type>::value &&
                         is_copy_assignable<second_type>::value,
@@ -521,7 +521,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
         return *this;
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pair& operator=(typename conditional<
                         is_move_assignable<first_type>::value &&
                         is_move_assignable<second_type>::value,
@@ -537,7 +537,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
     template <class _Tuple, _EnableB<
             _CheckTLC<_Tuple>::template __enable_assign<_Tuple>()
      > = false>
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pair& operator=(_Tuple&& __p) {
         first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p));
         second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p));
@@ -545,7 +545,7 @@ struct _LIBCPP_TEMPLATE_VIS pair
     }
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void
     swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value &&
                                __is_nothrow_swappable<second_type>::value)
@@ -558,10 +558,10 @@ private:
 
 #ifndef _LIBCPP_CXX03_LANG
     template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
-        _LIBCPP_INLINE_VISIBILITY
-        pair(piecewise_construct_t,
-             tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
-             __tuple_indices<_I1...>, __tuple_indices<_I2...>);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    pair(piecewise_construct_t,
+         tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args,
+         __tuple_indices<_I1...>, __tuple_indices<_I2...>);
 #endif
 };
 
@@ -619,7 +619,7 @@ operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
 }
 
 template <class _T1, class _T2>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename enable_if
 <
     __is_swappable<_T1>::value &&

diff  --git a/libcxx/include/version b/libcxx/include/version
index acedd03073cc..dc53be3937c4 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -42,6 +42,7 @@ __cpp_lib_concepts                                      201806L <concepts>
 __cpp_lib_constexpr_misc                                201811L <array> <functional> <iterator>
                                                                 <string_view> <tuple> <utility>
 __cpp_lib_constexpr_swap_algorithms                     201806L <algorithm>
+__cpp_lib_constexpr_utility                             201811L <utility>
 __cpp_lib_destroying_delete                             201806L <new>
 __cpp_lib_enable_shared_from_this                       201603L <memory>
 __cpp_lib_endian                                        201907L <bit>
@@ -227,6 +228,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // # define __cpp_lib_concepts                             201806L
 // # define __cpp_lib_constexpr_misc                       201811L
 // # define __cpp_lib_constexpr_swap_algorithms            201806L
+# define __cpp_lib_constexpr_utility                    201811L
 # if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
 #   define __cpp_lib_destroying_delete                  201806L
 # endif

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp
index 1fd38627a715..73762a4f12fa 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp
@@ -13,13 +13,14 @@
 
 // Test the feature test macros defined by <utility>
 
-/*  Constant                       Value
-    __cpp_lib_as_const             201510L [C++17]
-    __cpp_lib_constexpr_misc       201811L [C++2a]
-    __cpp_lib_exchange_function    201304L [C++14]
-    __cpp_lib_integer_sequence     201304L [C++14]
-    __cpp_lib_to_chars             201611L [C++17]
-    __cpp_lib_tuples_by_type       201304L [C++14]
+/*  Constant                        Value
+    __cpp_lib_as_const              201510L [C++17]
+    __cpp_lib_constexpr_misc        201811L [C++2a]
+    __cpp_lib_constexpr_utility     201811L [C++2a]
+    __cpp_lib_exchange_function     201304L [C++14]
+    __cpp_lib_integer_sequence      201304L [C++14]
+    __cpp_lib_to_chars              201611L [C++17]
+    __cpp_lib_tuples_by_type        201304L [C++14]
 */
 
 #include <utility>
@@ -35,6 +36,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_exchange_function
 #   error "__cpp_lib_exchange_function should not be defined before c++14"
 # endif
@@ -61,6 +66,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_exchange_function
 #   error "__cpp_lib_exchange_function should be defined in c++14"
 # endif
@@ -99,6 +108,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_exchange_function
 #   error "__cpp_lib_exchange_function should be defined in c++17"
 # endif
@@ -155,6 +168,13 @@
 #   endif
 # endif
 
+# ifndef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should be defined in c++2a"
+# endif
+# if __cpp_lib_constexpr_utility  != 201811L
+#   error "__cpp_lib_constexpr_utility  should have the value 201811L in c++2a"
+# endif
+
 # ifndef __cpp_lib_exchange_function
 #   error "__cpp_lib_exchange_function should be defined in c++2a"
 # endif

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 96a0fea6b918..5e485a2f585e 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -36,6 +36,7 @@
     __cpp_lib_concepts                             201806L [C++2a]
     __cpp_lib_constexpr_misc                       201811L [C++2a]
     __cpp_lib_constexpr_swap_algorithms            201806L [C++2a]
+    __cpp_lib_constexpr_utility                    201811L [C++2a]
     __cpp_lib_destroying_delete                    201806L [C++2a]
     __cpp_lib_enable_shared_from_this              201603L [C++17]
     __cpp_lib_endian                               201907L [C++2a]
@@ -194,6 +195,10 @@
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_destroying_delete
 #   error "__cpp_lib_destroying_delete should not be defined before c++2a"
 # endif
@@ -550,6 +555,10 @@
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_destroying_delete
 #   error "__cpp_lib_destroying_delete should not be defined before c++2a"
 # endif
@@ -1020,6 +1029,10 @@
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_destroying_delete
 #   error "__cpp_lib_destroying_delete should not be defined before c++2a"
 # endif
@@ -1721,6 +1734,13 @@
 #   endif
 # endif
 
+# ifndef __cpp_lib_constexpr_utility 
+#   error "__cpp_lib_constexpr_utility  should be defined in c++2a"
+# endif
+# if __cpp_lib_constexpr_utility  != 201811L
+#   error "__cpp_lib_constexpr_utility  should have the value 201811L in c++2a"
+# endif
+
 # if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
 #   ifndef __cpp_lib_destroying_delete
 #     error "__cpp_lib_destroying_delete should be defined in c++2a"

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
index 078d424a1ba3..becf36e66cf3 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
@@ -20,33 +20,51 @@
 #include "archetypes.h"
 #endif
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<int, short> P1;
-        typedef std::pair<double, long> P2;
-        P1 p1(3, static_cast<short>(4));
-        P2 p2;
-        p2 = p1;
-        assert(p2.first == 3);
-        assert(p2.second == 4);
-    }
-#if TEST_STD_VER >= 11
-    {
-       using C = TestTypes::TestType;
-       using P = std::pair<int, C>;
-       using T = std::pair<long, C>;
-       const T t(42, -42);
-       P p(101, 101);
-       C::reset_constructors();
-       p = t;
-       assert(C::constructed == 0);
-       assert(C::assigned == 1);
-       assert(C::copy_assigned == 1);
-       assert(C::move_assigned == 0);
-       assert(p.first == 42);
-       assert(p.second.value == -42);
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<int, short> P1;
+    typedef std::pair<double, long> P2;
+    P1 p1(3, static_cast<short>(4));
+    P2 p2;
+    p2 = p1;
+    assert(p2.first == 3);
+    assert(p2.second == 4);
+  }
+#if TEST_STD_VER >= 20
+  {
+    using C = ConstexprTestTypes::TestType;
+    using P = std::pair<int, C>;
+    using T = std::pair<long, C>;
+    const T t(42, -42);
+    P p(101, 101);
+    p = t;
+    assert(p.first == 42);
+    assert(p.second.value == -42);
+  }
+#elif TEST_STD_VER >= 11
+  {
+    using C = TestTypes::TestType;
+    using P = std::pair<int, C>;
+    using T = std::pair<long, C>;
+    const T t(42, -42);
+    P p(101, 101);
+    C::reset_constructors();
+    p = t;
+    assert(C::constructed == 0);
+    assert(C::assigned == 1);
+    assert(C::copy_assigned == 1);
+    assert(C::move_assigned == 0);
+    assert(p.first == 42);
+    assert(p.second.value == -42);
+  }
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
 #endif
 
   return 0;

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
index 303aedf50969..94e30aec3332 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
@@ -19,85 +19,81 @@
 #include <cassert>
 
 #include "test_macros.h"
-
-
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable() = default;
-  CopyAssignable(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable&&) = delete;
-};
-struct MoveAssignable {
-  MoveAssignable() = default;
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
+#include "archetypes.h"
 
 struct CountAssign {
-  static int copied;
-  static int moved;
-  static void reset() { copied = moved = 0; }
-  CountAssign() = default;
-  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
-  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
+  int copied = 0;
+  int moved = 0;
+  TEST_CONSTEXPR_CXX20 CountAssign() = default;
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
+    ++copied;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
+    ++moved;
+    return *this;
+  }
 };
-int CountAssign::copied = 0;
-int CountAssign::moved = 0;
 
 struct Incomplete;
 extern Incomplete inc_obj;
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<CopyAssignable, int> P;
-        const P p1(CopyAssignable(), short{4});
-        P p2;
-        p2 = p1;
-        assert(p2.second == 4);
-    }
-    {
-        using P = std::pair<int&, int&&>;
-        int x = 42;
-        int y = 101;
-        int x2 = -1;
-        int y2 = 300;
-        P p1(x, std::move(y));
-        P p2(x2, std::move(y2));
-        p1 = p2;
-        assert(p1.first == x2);
-        assert(p1.second == y2);
-    }
-    {
-        using P = std::pair<int, NonAssignable>;
-        static_assert(!std::is_copy_assignable<P>::value, "");
-    }
-    {
-        CountAssign::reset();
-        using P = std::pair<CountAssign, CopyAssignable>;
-        static_assert(std::is_copy_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = p2;
-        assert(CountAssign::copied == 1);
-        assert(CountAssign::moved == 0);
-    }
-    {
-        using P = std::pair<int, MoveAssignable>;
-        static_assert(!std::is_copy_assignable<P>::value, "");
-    }
-    {
-        using P = std::pair<int, Incomplete&>;
-        static_assert(!std::is_copy_assignable<P>::value, "");
-        P p(42, inc_obj);
-        assert(&p.second == &inc_obj);
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<ConstexprTestTypes::CopyOnly, int> P;
+    const P p1(ConstexprTestTypes::CopyOnly(), short{4});
+    P p2;
+    p2 = p1;
+    assert(p2.second == 4);
+  }
+  {
+    using P = std::pair<int&, int&&>;
+    int x = 42;
+    int y = 101;
+    int x2 = -1;
+    int y2 = 300;
+    P p1(x, std::move(y));
+    P p2(x2, std::move(y2));
+    p1 = p2;
+    assert(p1.first == x2);
+    assert(p1.second == y2);
+  }
+  {
+    using P = std::pair<int, ConstexprTestTypes::NonCopyable>;
+    static_assert(!std::is_copy_assignable<P>::value, "");
+  }
+  {
+    using P = std::pair<CountAssign, ConstexprTestTypes::Copyable>;
+    static_assert(std::is_copy_assignable<P>::value, "");
+    P p;
+    P p2;
+    p = p2;
+    assert(p.first.copied == 1);
+    assert(p.first.moved == 0);
+    assert(p2.first.copied == 0);
+    assert(p2.first.moved == 0);
+  }
+  {
+    using P = std::pair<int, ConstexprTestTypes::MoveAssignOnly>;
+    static_assert(!std::is_copy_assignable<P>::value, "");
+  }
+  {
+    using P = std::pair<int, Incomplete&>;
+    static_assert(!std::is_copy_assignable<P>::value, "");
+    P p(42, inc_obj);
+    assert(&p.second == &inc_obj);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
-    return 0;
+  return 0;
 }
 
 struct Incomplete {};

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
index 811e89015b48..cc4e4f5c1108 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
@@ -19,81 +19,78 @@
 #include <cassert>
 
 #include "test_macros.h"
-
-
-struct NonAssignable {
-  NonAssignable& operator=(NonAssignable const&) = delete;
-  NonAssignable& operator=(NonAssignable&&) = delete;
-};
-struct CopyAssignable {
-  CopyAssignable() = default;
-  CopyAssignable& operator=(CopyAssignable const&) = default;
-  CopyAssignable& operator=(CopyAssignable&&) = delete;
-};
-struct MoveAssignable {
-  MoveAssignable() = default;
-  MoveAssignable& operator=(MoveAssignable const&) = delete;
-  MoveAssignable& operator=(MoveAssignable&&) = default;
-};
+#include "archetypes.h"
 
 struct CountAssign {
-  static int copied;
-  static int moved;
-  static void reset() { copied = moved = 0; }
-  CountAssign() = default;
-  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
-  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
+  int copied = 0;
+  int moved = 0;
+  TEST_CONSTEXPR_CXX20 CountAssign() = default;
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
+    ++copied;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
+    ++moved;
+    return *this;
+  }
 };
-int CountAssign::copied = 0;
-int CountAssign::moved = 0;
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<std::unique_ptr<int>, int> P;
-        P p1(std::unique_ptr<int>(new int(3)), 4);
-        P p2;
-        p2 = std::move(p1);
-        assert(*p2.first == 3);
-        assert(p2.second == 4);
-    }
-    {
-        using P = std::pair<int&, int&&>;
-        int x = 42;
-        int y = 101;
-        int x2 = -1;
-        int y2 = 300;
-        P p1(x, std::move(y));
-        P p2(x2, std::move(y2));
-        p1 = std::move(p2);
-        assert(p1.first == x2);
-        assert(p1.second == y2);
-    }
-    {
-        using P = std::pair<int, NonAssignable>;
-        static_assert(!std::is_move_assignable<P>::value, "");
-    }
-    {
-        // The move decays to the copy constructor
-        CountAssign::reset();
-        using P = std::pair<CountAssign, CopyAssignable>;
-        static_assert(std::is_move_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = std::move(p2);
-        assert(CountAssign::moved == 0);
-        assert(CountAssign::copied == 1);
-    }
-    {
-        CountAssign::reset();
-        using P = std::pair<CountAssign, MoveAssignable>;
-        static_assert(std::is_move_assignable<P>::value, "");
-        P p;
-        P p2;
-        p = std::move(p2);
-        assert(CountAssign::moved == 1);
-        assert(CountAssign::copied == 0);
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<ConstexprTestTypes::MoveOnly, int> P;
+    P p1(3, 4);
+    P p2;
+    p2 = std::move(p1);
+    assert(p2.first.value == 3);
+    assert(p2.second == 4);
+  }
+  {
+    using P = std::pair<int&, int&&>;
+    int x = 42;
+    int y = 101;
+    int x2 = -1;
+    int y2 = 300;
+    P p1(x, std::move(y));
+    P p2(x2, std::move(y2));
+    p1 = std::move(p2);
+    assert(p1.first == x2);
+    assert(p1.second == y2);
+  }
+  {
+    using P = std::pair<int, ConstexprTestTypes::DefaultOnly>;
+    static_assert(!std::is_move_assignable<P>::value, "");
+  }
+  {
+    // The move decays to the copy constructor
+    using P = std::pair<CountAssign, ConstexprTestTypes::CopyOnly>;
+    static_assert(std::is_move_assignable<P>::value, "");
+    P p;
+    P p2;
+    p = std::move(p2);
+    assert(p.first.moved == 0);
+    assert(p.first.copied == 1);
+    assert(p2.first.moved == 0);
+    assert(p2.first.copied == 0);
+  }
+  {
+    using P = std::pair<CountAssign, ConstexprTestTypes::MoveOnly>;
+    static_assert(std::is_move_assignable<P>::value, "");
+    P p;
+    P p2;
+    p = std::move(p2);
+    assert(p.first.moved == 1);
+    assert(p.first.copied == 0);
+    assert(p2.first.moved == 0);
+    assert(p2.first.copied == 0);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
index ed56480b2f77..7267f7a2ef8b 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
@@ -17,46 +17,58 @@
 #include <utility>
 #include <memory>
 #include <cassert>
-#include <archetypes.h>
 
 #include "test_macros.h"
+#include "archetypes.h"
 
-struct Base
-{
-    virtual ~Base() {}
+struct Derived : ConstexprTestTypes::MoveOnly {
+  Derived() = default;
+  TEST_CONSTEXPR_CXX20 Derived(ConstexprTestTypes::MoveOnly&&){};
 };
-
-struct Derived
-    : public Base
-{
+struct CountAssign {
+  int copied = 0;
+  int moved = 0;
+  TEST_CONSTEXPR_CXX20 CountAssign() = default;
+  TEST_CONSTEXPR_CXX20 CountAssign(const int){};
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
+    ++copied;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
+    ++moved;
+    return *this;
+  }
 };
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<std::unique_ptr<Derived>, short> P1;
-        typedef std::pair<std::unique_ptr<Base>, long> P2;
-        P1 p1(std::unique_ptr<Derived>(), static_cast<short>(4));
-        P2 p2;
-        p2 = std::move(p1);
-        assert(p2.first == nullptr);
-        assert(p2.second == 4);
-    }
-    {
-       using C = TestTypes::TestType;
-       using P = std::pair<int, C>;
-       using T = std::pair<long, C>;
-       T t(42, -42);
-       P p(101, 101);
-       C::reset_constructors();
-       p = std::move(t);
-       assert(C::constructed == 0);
-       assert(C::assigned == 1);
-       assert(C::copy_assigned == 0);
-       assert(C::move_assigned == 1);
-       assert(p.first == 42);
-       assert(p.second.value == -42);
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<Derived, short> P1;
+    typedef std::pair<ConstexprTestTypes::MoveOnly, long> P2;
+    P1 p1(Derived(), static_cast<short>(4));
+    P2 p2;
+    p2 = std::move(p1);
+    assert(p2.second == 4);
+  }
+  {
+    using P = std::pair<int, CountAssign>;
+    using T = std::pair<long, CountAssign>;
+    T t(42, -42);
+    P p(101, 101);
+    p = std::move(t);
+    assert(p.first == 42);
+    assert(p.second.moved == 1);
+    assert(p.second.copied == 0);
+    assert(t.second.moved == 0);
+    assert(t.second.copied == 0);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp
index 358689ed0b97..42ddb4e6058b 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/const_pair_U_V.pass.cpp
@@ -23,18 +23,16 @@
 #include "test_macros.h"
 using namespace ImplicitTypes; // Get implicitly archetypes
 
-template <class T1, class U1,
-          bool CanCopy = true, bool CanConvert = CanCopy>
-void test_pair_const()
-{
-    using P1 = std::pair<T1, int>;
-    using P2 = std::pair<int, T1>;
-    using UP1 = std::pair<U1, int> const&;
-    using UP2 = std::pair<int, U1> const&;
-    static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
-    static_assert(test_convertible<P1, UP1>() == CanConvert, "");
-    static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
-    static_assert(test_convertible<P2,  UP2>() == CanConvert, "");
+template <class T1, class U1, bool CanCopy = true, bool CanConvert = CanCopy>
+TEST_CONSTEXPR_CXX20 void test_pair_const() {
+  using P1 = std::pair<T1, int>;
+  using P2 = std::pair<int, T1>;
+  using UP1 = std::pair<U1, int> const&;
+  using UP2 = std::pair<int, U1> const&;
+  static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "");
+  static_assert(test_convertible<P1, UP1>() == CanConvert, "");
+  static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "");
+  static_assert(test_convertible<P2, UP2>() == CanConvert, "");
 }
 
 template <class T, class U>
@@ -55,104 +53,115 @@ struct ImplicitT {
   int value;
 };
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<int, int> P1;
-        typedef std::pair<double, long> P2;
-        const P1 p1(3, 4);
-        const P2 p2 = p1;
-        assert(p2.first == 3);
-        assert(p2.second == 4);
-    }
-    {
-        // We allow derived types to use this constructor
-        using P1 = DPair<long, long>;
-        using P2 = std::pair<int, int>;
-        P1 p1(42, 101);
-        P2 p2(p1);
-        assert(p2.first == 42);
-        assert(p2.second == 101);
-    }
-    {
-        test_pair_const<AllCtors, AllCtors>(); // copy construction
-        test_pair_const<AllCtors, AllCtors&>();
-        test_pair_const<AllCtors, AllCtors&&>();
-        test_pair_const<AllCtors, const AllCtors&>();
-        test_pair_const<AllCtors, const AllCtors&&>();
-
-        test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors>(); // copy construction
-        test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>();
-        test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>();
-        test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, true, false>();
-        test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, true, false>();
-
-        test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction
-        test_pair_const<MoveOnly, MoveOnly&, false>();
-        test_pair_const<MoveOnly, MoveOnly&&, false>();
-
-        test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly, false>(); // copy construction
-        test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>();
-        test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, false>();
-
-        test_pair_const<CopyOnly, CopyOnly>();
-        test_pair_const<CopyOnly, CopyOnly&>();
-        test_pair_const<CopyOnly, CopyOnly&&>();
-
-        test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>();
-        test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>();
-        test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>();
-
-        test_pair_const<NonCopyable, NonCopyable, false>();
-        test_pair_const<NonCopyable, NonCopyable&, false>();
-        test_pair_const<NonCopyable, NonCopyable&&, false>();
-        test_pair_const<NonCopyable, const NonCopyable&, false>();
-        test_pair_const<NonCopyable, const NonCopyable&&, false>();
-    }
-
-    { // Test construction of references
-        test_pair_const<NonCopyable&, NonCopyable&>();
-        test_pair_const<NonCopyable&, NonCopyable&&>();
-        test_pair_const<NonCopyable&, NonCopyable const&, false>();
-        test_pair_const<NonCopyable const&, NonCopyable&&>();
-        test_pair_const<NonCopyable&&, NonCopyable&&, false>();
-
-        test_pair_const<ConvertingType&, int, false>();
-        test_pair_const<ExplicitTypes::ConvertingType&, int, false>();
-        // Unfortunately the below conversions are allowed and create dangling
-        // references.
-        //test_pair_const<ConvertingType&&, int>();
-        //test_pair_const<ConvertingType const&, int>();
-        //test_pair_const<ConvertingType const&&, int>();
-        // But these are not because the converting constructor is explicit.
-        test_pair_const<ExplicitTypes::ConvertingType&&, int, false>();
-        test_pair_const<ExplicitTypes::ConvertingType const&, int, false>();
-        test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>();
-
-    }
-    {
-        test_pair_const<AllCtors, int, false>();
-        test_pair_const<ExplicitTypes::AllCtors, int, false>();
-        test_pair_const<ConvertingType, int>();
-        test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
-
-        test_pair_const<ConvertingType, int>();
-        test_pair_const<ConvertingType, ConvertingType>();
-        test_pair_const<ConvertingType, ConvertingType const&>();
-        test_pair_const<ConvertingType, ConvertingType&>();
-        test_pair_const<ConvertingType, ConvertingType&&>();
-
-        test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>();
-
-        test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType>();
-        test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType const&, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&, true, false>();
-        test_pair_const<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&&, true, false>();
-    }
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<int, int> P1;
+    typedef std::pair<double, long> P2;
+    const P1 p1(3, 4);
+    const P2 p2 = p1;
+    assert(p2.first == 3);
+    assert(p2.second == 4);
+  }
+  {
+    // We allow derived types to use this constructor
+    using P1 = DPair<long, long>;
+    using P2 = std::pair<int, int>;
+    P1 p1(42, 101);
+    P2 p2(p1);
+    assert(p2.first == 42);
+    assert(p2.second == 101);
+  }
+  {
+    test_pair_const<AllCtors, AllCtors>(); // copy construction
+    test_pair_const<AllCtors, AllCtors&>();
+    test_pair_const<AllCtors, AllCtors&&>();
+    test_pair_const<AllCtors, const AllCtors&>();
+    test_pair_const<AllCtors, const AllCtors&&>();
+
+    test_pair_const<ExplicitTypes::AllCtors,
+                    ExplicitTypes::AllCtors>(); // copy construction
+    test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true,
+                    false>();
+    test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true,
+                    false>();
+    test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&,
+                    true, false>();
+    test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&,
+                    true, false>();
+
+    test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction
+    test_pair_const<MoveOnly, MoveOnly&, false>();
+    test_pair_const<MoveOnly, MoveOnly&&, false>();
+
+    test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly,
+                    false>(); // copy construction
+    test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>();
+    test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&,
+                    false>();
+
+    test_pair_const<CopyOnly, CopyOnly>();
+    test_pair_const<CopyOnly, CopyOnly&>();
+    test_pair_const<CopyOnly, CopyOnly&&>();
+
+    test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>();
+    test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true,
+                    false>();
+    test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true,
+                    false>();
+
+    test_pair_const<NonCopyable, NonCopyable, false>();
+    test_pair_const<NonCopyable, NonCopyable&, false>();
+    test_pair_const<NonCopyable, NonCopyable&&, false>();
+    test_pair_const<NonCopyable, const NonCopyable&, false>();
+    test_pair_const<NonCopyable, const NonCopyable&&, false>();
+  }
+
+  { // Test construction of references
+    test_pair_const<NonCopyable&, NonCopyable&>();
+    test_pair_const<NonCopyable&, NonCopyable&&>();
+    test_pair_const<NonCopyable&, NonCopyable const&, false>();
+    test_pair_const<NonCopyable const&, NonCopyable&&>();
+    test_pair_const<NonCopyable&&, NonCopyable&&, false>();
+
+    test_pair_const<ConvertingType&, int, false>();
+    test_pair_const<ExplicitTypes::ConvertingType&, int, false>();
+    // Unfortunately the below conversions are allowed and create dangling
+    // references.
+    //test_pair_const<ConvertingType&&, int>();
+    //test_pair_const<ConvertingType const&, int>();
+    //test_pair_const<ConvertingType const&&, int>();
+    // But these are not because the converting constructor is explicit.
+    test_pair_const<ExplicitTypes::ConvertingType&&, int, false>();
+    test_pair_const<ExplicitTypes::ConvertingType const&, int, false>();
+    test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>();
+  }
+  {
+    test_pair_const<AllCtors, int, false>();
+    test_pair_const<ExplicitTypes::AllCtors, int, false>();
+    test_pair_const<ConvertingType, int>();
+    test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
+
+    test_pair_const<ConvertingType, int>();
+    test_pair_const<ConvertingType, ConvertingType>();
+    test_pair_const<ConvertingType, ConvertingType const&>();
+    test_pair_const<ConvertingType, ConvertingType&>();
+    test_pair_const<ConvertingType, ConvertingType&&>();
+
+    test_pair_const<ExplicitTypes::ConvertingType, int, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>();
+
+    test_pair_const<ExplicitTypes::ConvertingType,
+                    ExplicitTypes::ConvertingType>();
+    test_pair_const<ExplicitTypes::ConvertingType,
+                    ExplicitTypes::ConvertingType const&, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType,
+                    ExplicitTypes::ConvertingType&, true, false>();
+    test_pair_const<ExplicitTypes::ConvertingType,
+                    ExplicitTypes::ConvertingType&&, true, false>();
+  }
 #if TEST_STD_VER > 11
     {
         typedef std::pair<int, int> P1;
@@ -171,14 +180,22 @@ int main(int, char**)
         static_assert(p2.second.value == 101, "");
     }
     {
-        using P1 = std::pair<int, int>;
-        using P2 = std::pair<ImplicitT, ImplicitT>;
-        constexpr P1 p1(42, 101);
-        constexpr P2 p2 = p1;
-        static_assert(p2.first.value == 42, "");
-        static_assert(p2.second.value == 101, "");
+      using P1 = std::pair<int, int>;
+      using P2 = std::pair<ImplicitT, ImplicitT>;
+      constexpr P1 p1(42, 101);
+      constexpr P2 p2 = p1;
+      static_assert(p2.first.value == 42, "");
+      static_assert(p2.second.value == 101, "");
     }
 #endif
+    return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp
index 203209d5e634..37bbb9501769 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/piecewise.pass.cpp
@@ -22,18 +22,24 @@
 
 #include "test_macros.h"
 
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<int, int*> P1;
+    typedef std::pair<int*, int> P2;
+    typedef std::pair<P1, P2> P3;
+    P3 p3(std::piecewise_construct, std::tuple<int, int*>(3, nullptr),
+          std::tuple<int*, int>(nullptr, 4));
+    assert(p3.first == P1(3, nullptr));
+    assert(p3.second == P2(nullptr, 4));
+  }
+  return true;
+}
 
-int main(int, char**)
-{
-    {
-        typedef std::pair<int, int*> P1;
-        typedef std::pair<int*, int> P2;
-        typedef std::pair<P1, P2> P3;
-        P3 p3(std::piecewise_construct, std::tuple<int, int*>(3, nullptr),
-                                        std::tuple<int*, int>(nullptr, 4));
-        assert(p3.first == P1(3, nullptr));
-        assert(p3.second == P2(nullptr, 4));
-    }
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp
index 9a497e5ac532..a2d720ff42ea 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/swap.pass.cpp
@@ -19,35 +19,40 @@
 
 struct S {
     int i;
-    S() : i(0) {}
-    S(int j) : i(j) {}
-    S * operator& () { assert(false); return this; }
-    S const * operator& () const { assert(false); return this; }
-    bool operator==(int x) const { return i == x; }
-    };
-
-int main(int, char**)
-{
-    {
-        typedef std::pair<int, short> P1;
-        P1 p1(3, static_cast<short>(4));
-        P1 p2(5, static_cast<short>(6));
-        p1.swap(p2);
-        assert(p1.first == 5);
-        assert(p1.second == 6);
-        assert(p2.first == 3);
-        assert(p2.second == 4);
-    }
-    {
-        typedef std::pair<int, S> P1;
-        P1 p1(3, S(4));
-        P1 p2(5, S(6));
-        p1.swap(p2);
-        assert(p1.first == 5);
-        assert(p1.second == 6);
-        assert(p2.first == 3);
-        assert(p2.second == 4);
-    }
+    TEST_CONSTEXPR_CXX20 S() : i(0) {}
+    TEST_CONSTEXPR_CXX20 S(int j) : i(j) {}
+    TEST_CONSTEXPR_CXX20 bool operator==(int x) const { return i == x; }
+};
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    typedef std::pair<int, short> P1;
+    P1 p1(3, static_cast<short>(4));
+    P1 p2(5, static_cast<short>(6));
+    p1.swap(p2);
+    assert(p1.first == 5);
+    assert(p1.second == 6);
+    assert(p2.first == 3);
+    assert(p2.second == 4);
+  }
+  {
+    typedef std::pair<int, S> P1;
+    P1 p1(3, S(4));
+    P1 p2(5, S(6));
+    p1.swap(p2);
+    assert(p1.first == 5);
+    assert(p1.second == 6);
+    assert(p2.first == 3);
+    assert(p2.second == 4);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
 
   return 0;
 }

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index b77f88489d9d..88241614420a 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -607,6 +607,12 @@ def add_version_header(tc):
    "depends": "defined(__cpp_concepts) && __cpp_concepts >= 201811L",
    "internal_depends": "defined(__cpp_concepts) && __cpp_concepts >= 201811L",
    },
+  {"name": "__cpp_lib_constexpr_utility ",
+   "values": {
+     "c++2a": int(201811),
+   },
+   "headers": ["utility"],
+   },
 ]], key=lambda tc: tc["name"])
 
 def get_std_dialects():


        


More information about the libcxx-commits mailing list