| // Verify P2321R2 "zip" enhancements to std::pair. |
| // { dg-options "-std=gnu++23" } |
| // { dg-do run { target c++23 } } |
| |
| #include <utility> |
| #include <testsuite_hooks.h> |
| |
| using std::pair; |
| |
| struct A { }; |
| |
| constexpr bool |
| test01() |
| { |
| struct B { bool v; constexpr B(A&) : v(true) { } }; |
| |
| // template<class U1, class U2> |
| // constexpr explicit(false) pair(pair<U1, U2>&); |
| |
| pair<A, int> p2a0; |
| pair<B, int> p2b0 = p2a0; |
| VERIFY( std::get<0>(p2b0).v ); |
| |
| pair<int, A> p2a1; |
| pair<int, B> p2b1 = p2a1; |
| VERIFY( std::get<1>(p2b1).v ); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test02() |
| { |
| struct B { bool v; explicit constexpr B(A&) : v(true) { } }; |
| |
| // template<class U1, class U2> |
| // constexpr explicit(true) pair(pair<U1, U2>&); |
| |
| static_assert(!std::is_convertible_v<pair<A, int>&, pair<B, int>>); |
| static_assert(!std::is_convertible_v<pair<int, A>&, pair<int, B>>); |
| |
| pair<A, int> p2a0; |
| pair<B, int> p2b0(p2a0); |
| VERIFY( std::get<0>(p2b0).v ); |
| |
| pair<int, A> p2a1; |
| pair<int, B> p2b1(p2a1); |
| VERIFY( std::get<1>(p2b1).v ); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test03() |
| { |
| struct B { bool v; constexpr B(const A&&) : v(true) { } }; |
| |
| // template<class U1, class U2> |
| // constexpr explicit(false) pair(const pair<U1, U2>&&); |
| |
| const pair<A, int> p2a0; |
| pair<B, int> p2b0 = std::move(p2a0); |
| VERIFY( std::get<0>(p2b0).v ); |
| |
| const pair<int, A> p2a1; |
| pair<int, B> p2b1 = std::move(p2a1); |
| VERIFY( std::get<1>(p2b1).v ); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test04() |
| { |
| struct B { bool v; explicit constexpr B(const A&&) : v(true) { } }; |
| |
| // template<class U1, class U2> |
| // constexpr explicit(true) pair(const pair<U1, U2>&&); |
| |
| static_assert(!std::is_convertible_v<const pair<A, int>&&, pair<B, int>>); |
| static_assert(!std::is_convertible_v<const pair<int, A>&&, pair<int, B>>); |
| |
| const pair<A, int> p2a0; |
| pair<B, int> p2b0(std::move(p2a0)); |
| VERIFY( std::get<0>(p2b0).v ); |
| |
| const pair<int, A> p2a1; |
| pair<int, B> p2b1(std::move(p2a1)); |
| VERIFY( std::get<1>(p2b1).v ); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test05() |
| { |
| struct B |
| { |
| mutable bool v; |
| constexpr const B& operator=(const A&) const { v = true; return *this; } |
| }; |
| |
| // template<class U1, class U2> |
| // constexpr const pair& operator=(const pair<U1, U2>&) const; |
| |
| const pair<A, A> p2a; |
| const pair<B, B> p2b; |
| p2b = p2a; |
| |
| return true; |
| } |
| |
| constexpr bool |
| test06() |
| { |
| struct B |
| { |
| mutable bool v; |
| constexpr const B& operator=(A&&) const { v = true; return *this; } |
| }; |
| |
| // template<class U1, class U2> |
| // constexpr const pair& operator=(pair<U1, U2>&&) const; |
| |
| pair<A, A> p2a; |
| const pair<B, B> p2b; |
| p2b = std::move(p2a); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test07() |
| { |
| struct B |
| { |
| mutable bool v; |
| constexpr const B& operator=(const B&) const { v = true; return *this; } |
| }; |
| |
| // constexpr const pair& operator=(const pair&) const; |
| |
| const pair<B, B> t2a; |
| const pair<B, B> t2b; |
| t2b = t2a; |
| VERIFY( std::get<0>(t2b).v ); |
| VERIFY( std::get<1>(t2b).v ); |
| |
| return true; |
| } |
| |
| constexpr bool |
| test08() |
| { |
| struct B |
| { |
| mutable bool v; |
| constexpr const B& operator=(B&&) const { v = true; return *this; } |
| }; |
| |
| // constexpr const pair& operator=(pair&&) const; |
| |
| pair<B, B> t2a; |
| const pair<B, B> t2b; |
| t2b = std::move(t2a); |
| VERIFY( std::get<0>(t2b).v ); |
| VERIFY( std::get<1>(t2b).v ); |
| |
| return true; |
| } |
| |
| struct S |
| { |
| mutable int v = 0; |
| friend constexpr void swap(S&& x, S&& y) = delete; |
| friend constexpr void swap(const S& x, const S& y) { ++x.v; ++y.v; } |
| }; |
| |
| constexpr bool |
| test09() |
| { |
| const pair<S, S> t2, u2; |
| std::swap(t2, u2); |
| VERIFY( std::get<0>(t2).v == 1 ); |
| VERIFY( std::get<0>(u2).v == 1 ); |
| VERIFY( std::get<1>(t2).v == 1 ); |
| VERIFY( std::get<1>(u2).v == 1 ); |
| |
| static_assert(!std::is_swappable_v<const pair<A, int>&>); |
| static_assert(!std::is_swappable_v<const pair<int, A>&>); |
| |
| return true; |
| } |
| |
| int |
| main() |
| { |
| static_assert(test01()); |
| static_assert(test02()); |
| static_assert(test03()); |
| static_assert(test04()); |
| // FIXME: G++ doesn't support reading mutable members during constexpr (PR c++/92505). |
| test05(); |
| test06(); |
| test07(); |
| test08(); |
| test09(); |
| } |