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 const pair& operator=(P&&) const; // 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
32 std::array
<int, 2> a
= {1, 2};
33 std::pair
<int&, int&> const p
= {x
, y
};
34 std::same_as
<std::pair
<int&, int&> const&> decltype(auto) result
= (p
= a
);
35 assert(&result
== &p
);
38 static_assert(!std::is_assignable_v
<std::pair
<int&, int&> const&, std::array
<int, 1>>); // too small
39 static_assert( std::is_assignable_v
<std::pair
<int&, int&> const&, std::array
<int, 2>>); // works (test the test)
40 static_assert(!std::is_assignable_v
<std::pair
<int&, int&> const&, std::array
<int, 3>>); // too large
43 // Check from std::tuple
46 std::tuple
<int, int> a
= {1, 2};
47 std::pair
<int&, int&> const p
= {x
, y
};
48 std::same_as
<std::pair
<int&, int&> const&> decltype(auto) result
= (p
= a
);
49 assert(&result
== &p
);
52 static_assert(!std::is_assignable_v
<std::pair
<int&, int&> const&, std::tuple
<int>>); // too small
53 static_assert( std::is_assignable_v
<std::pair
<int&, int&> const&, std::tuple
<int, int>>); // works (test the test)
54 static_assert(!std::is_assignable_v
<std::pair
<int&, int&> const&, std::tuple
<int, int, int>>); // too large
57 // Make sure it works for ranges::subrange. This actually deserves an explanation: even though
58 // the assignment operator explicitly excludes ranges::subrange specializations, such assignments
59 // end up working because of ranges::subrange's implicit conversion to pair-like types.
60 // This test ensures that the interoperability works as intended.
62 struct ConstAssignable
{
63 mutable int* ptr
= nullptr;
64 ConstAssignable() = default;
65 constexpr ConstAssignable(int* p
) : ptr(p
) { } // enable `subrange::operator pair-like`
66 constexpr ConstAssignable
const& operator=(ConstAssignable
const& other
) const { ptr
= other
.ptr
; return *this; }
68 constexpr ConstAssignable(ConstAssignable
const&) = default; // defeat -Wdeprecated-copy
69 constexpr ConstAssignable
& operator=(ConstAssignable
const&) = default; // defeat -Wdeprecated-copy
71 int data
[] = {1, 2, 3, 4, 5};
72 std::ranges::subrange
<int*> a(data
);
73 std::pair
<ConstAssignable
, ConstAssignable
> const p
;
74 std::same_as
<std::pair
<ConstAssignable
, ConstAssignable
> const&> decltype(auto) result
= (p
= a
);
75 assert(&result
== &p
);
76 assert(p
.first
.ptr
== data
);
77 assert(p
.second
.ptr
== data
+ 5);
81 // Make sure we allow element conversion from a pair-like
83 struct ConstAssignable
{
85 ConstAssignable() = default;
86 constexpr ConstAssignable
const& operator=(int v
) const { val
= v
; return *this; }
88 std::tuple
<int, int> a
= {1, 2};
89 std::pair
<ConstAssignable
, ConstAssignable
> const p
;
90 std::same_as
<std::pair
<ConstAssignable
, ConstAssignable
> const&> decltype(auto) result
= (p
= a
);
91 assert(&result
== &p
);
92 assert(p
.first
.val
== 1);
93 assert(p
.second
.val
== 2);
94 static_assert(!std::is_assignable_v
<std::pair
<ConstAssignable
, ConstAssignable
> const&, std::tuple
<void*, int>>); // first not convertible
95 static_assert(!std::is_assignable_v
<std::pair
<ConstAssignable
, ConstAssignable
> const&, std::tuple
<int, void*>>); // second not convertible
96 static_assert( std::is_assignable_v
<std::pair
<ConstAssignable
, ConstAssignable
> const&, std::tuple
<int, int>>); // works (test the test)
99 // Make sure we forward the pair-like elements
103 NoCopy(NoCopy
const&) = delete;
104 NoCopy(NoCopy
&&) = default;
105 NoCopy
& operator=(NoCopy
const&) = delete;
106 constexpr NoCopy
const& operator=(NoCopy
&&) const { return *this; }
108 std::tuple
<NoCopy
, NoCopy
> a
;
109 std::pair
<NoCopy
, NoCopy
> const p
;
116 int main(int, char**) {
118 static_assert(test());