diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -184,6 +184,8 @@ ------------------------------------------------- ----------------- ``__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 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1393,7 +1393,7 @@ template template -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 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -499,7 +499,7 @@ second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} template - _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::value && @@ -508,7 +508,7 @@ typename __make_tuple_indices::type(), typename __make_tuple_indices::type()) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair& operator=(typename conditional< is_copy_assignable::value && is_copy_assignable::value, @@ -521,7 +521,7 @@ return *this; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 pair& operator=(typename conditional< is_move_assignable::value && is_move_assignable::value, @@ -537,7 +537,7 @@ template ::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 @@ } #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) @@ -558,10 +558,10 @@ #ifndef _LIBCPP_CXX03_LANG template - _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 @@ } template -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 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -42,6 +42,7 @@ __cpp_lib_constexpr_misc 201811L __cpp_lib_constexpr_swap_algorithms 201806L +__cpp_lib_constexpr_utility 201811L __cpp_lib_destroying_delete 201806L __cpp_lib_enable_shared_from_this 201603L __cpp_lib_endian 201907L @@ -227,6 +228,7 @@ // # 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 --- 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 -/* 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 @@ -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 --- 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 --- 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 P1; - typedef std::pair P2; - P1 p1(3, static_cast(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; - using T = std::pair; - 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 P1; + typedef std::pair P2; + P1 p1(3, static_cast(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; + using T = std::pair; + 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; + using T = std::pair; + 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 --- 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 #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 P; - const P p1(CopyAssignable(), short{4}); - P p2; - p2 = p1; - assert(p2.second == 4); - } - { - using P = std::pair; - 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; - static_assert(!std::is_copy_assignable

::value, ""); - } - { - CountAssign::reset(); - using P = std::pair; - static_assert(std::is_copy_assignable

::value, ""); - P p; - P p2; - p = p2; - assert(CountAssign::copied == 1); - assert(CountAssign::moved == 0); - } - { - using P = std::pair; - static_assert(!std::is_copy_assignable

::value, ""); - } - { - using P = std::pair; - static_assert(!std::is_copy_assignable

::value, ""); - P p(42, inc_obj); - assert(&p.second == &inc_obj); - } +TEST_CONSTEXPR_CXX20 bool test() { + { + typedef std::pair P; + const P p1(ConstexprTestTypes::CopyOnly(), short{4}); + P p2; + p2 = p1; + assert(p2.second == 4); + } + { + using P = std::pair; + 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; + static_assert(!std::is_copy_assignable

::value, ""); + } + { + using P = std::pair; + static_assert(std::is_copy_assignable

::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; + static_assert(!std::is_copy_assignable

::value, ""); + } + { + using P = std::pair; + static_assert(!std::is_copy_assignable

::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 --- 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 #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, int> P; - P p1(std::unique_ptr(new int(3)), 4); - P p2; - p2 = std::move(p1); - assert(*p2.first == 3); - assert(p2.second == 4); - } - { - using P = std::pair; - 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; - static_assert(!std::is_move_assignable

::value, ""); - } - { - // The move decays to the copy constructor - CountAssign::reset(); - using P = std::pair; - static_assert(std::is_move_assignable

::value, ""); - P p; - P p2; - p = std::move(p2); - assert(CountAssign::moved == 0); - assert(CountAssign::copied == 1); - } - { - CountAssign::reset(); - using P = std::pair; - static_assert(std::is_move_assignable

::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 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 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; + static_assert(!std::is_move_assignable

::value, ""); + } + { + // The move decays to the copy constructor + using P = std::pair; + static_assert(std::is_move_assignable

::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; + static_assert(std::is_move_assignable

::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 --- 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 #include #include -#include #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, short> P1; - typedef std::pair, long> P2; - P1 p1(std::unique_ptr(), static_cast(4)); - P2 p2; - p2 = std::move(p1); - assert(p2.first == nullptr); - assert(p2.second == 4); - } - { - using C = TestTypes::TestType; - using P = std::pair; - using T = std::pair; - 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 P1; + typedef std::pair P2; + P1 p1(Derived(), static_cast(4)); + P2 p2; + p2 = std::move(p1); + assert(p2.second == 4); + } + { + using P = std::pair; + using T = std::pair; + 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 --- 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 -void test_pair_const() -{ - using P1 = std::pair; - using P2 = std::pair; - using UP1 = std::pair const&; - using UP2 = std::pair const&; - static_assert(std::is_constructible::value == CanCopy, ""); - static_assert(test_convertible() == CanConvert, ""); - static_assert(std::is_constructible::value == CanCopy, ""); - static_assert(test_convertible() == CanConvert, ""); +template +TEST_CONSTEXPR_CXX20 void test_pair_const() { + using P1 = std::pair; + using P2 = std::pair; + using UP1 = std::pair const&; + using UP2 = std::pair const&; + static_assert(std::is_constructible::value == CanCopy, ""); + static_assert(test_convertible() == CanConvert, ""); + static_assert(std::is_constructible::value == CanCopy, ""); + static_assert(test_convertible() == CanConvert, ""); } template @@ -55,104 +53,115 @@ int value; }; -int main(int, char**) -{ - { - typedef std::pair P1; - typedef std::pair 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; - using P2 = std::pair; - P1 p1(42, 101); - P2 p2(p1); - assert(p2.first == 42); - assert(p2.second == 101); - } - { - test_pair_const(); // copy construction - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); // copy construction - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); // copy construction - test_pair_const(); - test_pair_const(); - - test_pair_const(); // copy construction - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - } - - { // Test construction of references - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - // Unfortunately the below conversions are allowed and create dangling - // references. - //test_pair_const(); - //test_pair_const(); - //test_pair_const(); - // But these are not because the converting constructor is explicit. - test_pair_const(); - test_pair_const(); - test_pair_const(); - - } - { - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - - test_pair_const(); - test_pair_const(); - test_pair_const(); - test_pair_const(); - } +TEST_CONSTEXPR_CXX20 bool test() { + { + typedef std::pair P1; + typedef std::pair 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; + using P2 = std::pair; + P1 p1(42, 101); + P2 p2(p1); + assert(p2.first == 42); + assert(p2.second == 101); + } + { + test_pair_const(); // copy construction + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); // copy construction + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); // copy construction + test_pair_const(); + test_pair_const(); + + test_pair_const(); // copy construction + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + } + + { // Test construction of references + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + // Unfortunately the below conversions are allowed and create dangling + // references. + //test_pair_const(); + //test_pair_const(); + //test_pair_const(); + // But these are not because the converting constructor is explicit. + test_pair_const(); + test_pair_const(); + test_pair_const(); + } + { + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + + test_pair_const(); + test_pair_const(); + test_pair_const(); + test_pair_const(); + } #if TEST_STD_VER > 11 { typedef std::pair P1; @@ -171,14 +180,22 @@ static_assert(p2.second.value == 101, ""); } { - using P1 = std::pair; - using P2 = std::pair; - 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; + using P2 = std::pair; + 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 --- 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 P1; + typedef std::pair P2; + typedef std::pair P3; + P3 p3(std::piecewise_construct, std::tuple(3, nullptr), + std::tuple(nullptr, 4)); + assert(p3.first == P1(3, nullptr)); + assert(p3.second == P2(nullptr, 4)); + } + return true; +} -int main(int, char**) -{ - { - typedef std::pair P1; - typedef std::pair P2; - typedef std::pair P3; - P3 p3(std::piecewise_construct, std::tuple(3, nullptr), - std::tuple(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 --- 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 P1; - P1 p1(3, static_cast(4)); - P1 p2(5, static_cast(6)); - p1.swap(p2); - assert(p1.first == 5); - assert(p1.second == 6); - assert(p2.first == 3); - assert(p2.second == 4); - } - { - typedef std::pair 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 P1; + P1 p1(3, static_cast(4)); + P1 p2(5, static_cast(6)); + p1.swap(p2); + assert(p1.first == 5); + assert(p1.second == 6); + assert(p2.first == 3); + assert(p2.second == 4); + } + { + typedef std::pair 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 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -607,6 +607,12 @@ "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():