[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