1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
13 // template <class T1, class T2> struct pair
15 // template <pair-like P> constexpr pair& operator=(P&&); // since C++23
23 #include <type_traits>
26 constexpr bool test() {
27 // Make sure assignment works from array and tuple
29 // Check from std::array
31 std::array
<int, 2> a
= {1, 2};
32 std::pair
<int, int> p
;
33 std::same_as
<std::pair
<int, int>&> decltype(auto) result
= (p
= a
);
34 assert(&result
== &p
);
36 assert(p
.second
== 2);
37 static_assert(!std::is_assignable_v
<std::pair
<int, int>&, std::array
<int, 1>>); // too small
38 static_assert( std::is_assignable_v
<std::pair
<int, int>&, std::array
<int, 2>>); // works (test the test)
39 static_assert(!std::is_assignable_v
<std::pair
<int, int>&, std::array
<int, 3>>); // too large
42 // Check from std::tuple
44 std::tuple
<int, int> a
= {1, 2};
45 std::pair
<int, int> p
;
46 std::same_as
<std::pair
<int, int>&> decltype(auto) result
= (p
= a
);
47 assert(&result
== &p
);
49 assert(p
.second
== 2);
50 static_assert(!std::is_assignable_v
<std::pair
<int, int>&, std::tuple
<int>>); // too small
51 static_assert( std::is_assignable_v
<std::pair
<int, int>&, std::tuple
<int, int>>); // works (test the test)
52 static_assert(!std::is_assignable_v
<std::pair
<int, int>&, std::tuple
<int, int, int>>); // too large
55 // Make sure it works for ranges::subrange. This actually deserves an explanation: even though
56 // the assignment operator explicitly excludes ranges::subrange specializations, such assignments
57 // end up working because of ranges::subrange's implicit conversion to pair-like types.
58 // This test ensures that the interoperability works as intended.
62 Assignable() = default;
63 constexpr Assignable(int* p
) : ptr(p
) { } // enable `subrange::operator pair-like`
64 constexpr Assignable
& operator=(Assignable
const&) = default;
66 int data
[] = {1, 2, 3, 4, 5};
67 std::ranges::subrange
<int*> a(data
);
68 std::pair
<Assignable
, Assignable
> p
;
69 std::same_as
<std::pair
<Assignable
, Assignable
>&> decltype(auto) result
= (p
= a
);
70 assert(&result
== &p
);
71 assert(p
.first
.ptr
== data
);
72 assert(p
.second
.ptr
== data
+ 5);
76 // Make sure we allow element conversion from a pair-like
78 std::tuple
<int, char const*> a
= {34, "hello world"};
79 std::pair
<long, std::string
> p
;
80 std::same_as
<std::pair
<long, std::string
>&> decltype(auto) result
= (p
= a
);
81 assert(&result
== &p
);
82 assert(p
.first
== 34);
83 assert(p
.second
== std::string("hello world"));
84 static_assert(!std::is_assignable_v
<std::pair
<long, std::string
>&, std::tuple
<char*, std::string
>>); // first not convertible
85 static_assert(!std::is_assignable_v
<std::pair
<long, std::string
>&, std::tuple
<long, void*>>); // second not convertible
86 static_assert( std::is_assignable_v
<std::pair
<long, std::string
>&, std::tuple
<long, std::string
>>); // works (test the test)
89 // Make sure we forward the pair-like elements
93 NoCopy(NoCopy
const&) = delete;
94 NoCopy(NoCopy
&&) = default;
95 NoCopy
& operator=(NoCopy
const&) = delete;
96 NoCopy
& operator=(NoCopy
&&) = default;
98 std::tuple
<NoCopy
, NoCopy
> a
;
99 std::pair
<NoCopy
, NoCopy
> p
;
106 int main(int, char**) {
108 static_assert(test());