1 | //===----------------------------------------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03 |
10 | |
11 | // <utility> |
12 | |
13 | // template <class T1, class T2> struct pair |
14 | |
15 | // template <class U, class V> |
16 | // constexpr explicit(see below) pair(pair<U, V>&& p); |
17 | |
18 | #include <utility> |
19 | #include <memory> |
20 | #include <cassert> |
21 | |
22 | #include "archetypes.h" |
23 | #include "test_convertible.h" |
24 | |
25 | #include "test_macros.h" |
26 | using namespace ImplicitTypes; // Get implicitly archetypes |
27 | |
28 | template <class T1, class U1, |
29 | bool CanCopy = true, bool CanConvert = CanCopy> |
30 | void test_pair_rv() |
31 | { |
32 | using P1 = std::pair<T1, int>; |
33 | using P2 = std::pair<int, T1>; |
34 | using UP1 = std::pair<U1, int>&&; |
35 | using UP2 = std::pair<int, U1>&&; |
36 | static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "" ); |
37 | static_assert(test_convertible<P1, UP1>() == CanConvert, "" ); |
38 | static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "" ); |
39 | static_assert(test_convertible<P2, UP2>() == CanConvert, "" ); |
40 | } |
41 | |
42 | struct Base |
43 | { |
44 | virtual ~Base() {} |
45 | }; |
46 | |
47 | struct Derived |
48 | : public Base |
49 | { |
50 | }; |
51 | |
52 | |
53 | template <class T, class U> |
54 | struct DPair : public std::pair<T, U> { |
55 | using Base = std::pair<T, U>; |
56 | using Base::Base; |
57 | }; |
58 | |
59 | struct ExplicitT { |
60 | constexpr explicit ExplicitT(int x) : value(x) {} |
61 | int value; |
62 | }; |
63 | |
64 | struct ImplicitT { |
65 | constexpr ImplicitT(int x) : value(x) {} |
66 | int value; |
67 | }; |
68 | |
69 | struct NotCopyOrMoveConstructible { |
70 | NotCopyOrMoveConstructible() = default; |
71 | NotCopyOrMoveConstructible(NotCopyOrMoveConstructible const&) = delete; |
72 | NotCopyOrMoveConstructible(NotCopyOrMoveConstructible&&) = delete; |
73 | }; |
74 | |
75 | struct NonCopyConstructible { |
76 | NonCopyConstructible(NonCopyConstructible const&) = delete; |
77 | NonCopyConstructible(NonCopyConstructible&&) = default; |
78 | }; |
79 | |
80 | int main(int, char**) |
81 | { |
82 | { |
83 | typedef std::pair<std::unique_ptr<Derived>, int> P1; |
84 | typedef std::pair<std::unique_ptr<Base>, long> P2; |
85 | P1 p1(std::unique_ptr<Derived>(), 4); |
86 | P2 p2 = std::move(p1); |
87 | assert(p2.first == nullptr); |
88 | assert(p2.second == 4); |
89 | } |
90 | { |
91 | // We allow derived types to use this constructor |
92 | using P1 = DPair<long, long>; |
93 | using P2 = std::pair<int, int>; |
94 | P1 p1(42, 101); |
95 | P2 p2(std::move(p1)); |
96 | assert(p2.first == 42); |
97 | assert(p2.second == 101); |
98 | } |
99 | { |
100 | test_pair_rv<AllCtors, AllCtors>(); |
101 | test_pair_rv<AllCtors, AllCtors&>(); |
102 | test_pair_rv<AllCtors, AllCtors&&>(); |
103 | test_pair_rv<AllCtors, const AllCtors&>(); |
104 | test_pair_rv<AllCtors, const AllCtors&&>(); |
105 | |
106 | test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors>(); |
107 | test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, false>(); |
108 | test_pair_rv<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, false>(); |
109 | test_pair_rv<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, true, false>(); |
110 | test_pair_rv<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, true, false>(); |
111 | |
112 | test_pair_rv<MoveOnly, MoveOnly>(); |
113 | test_pair_rv<MoveOnly, MoveOnly&, false>(); |
114 | test_pair_rv<MoveOnly, MoveOnly&&>(); |
115 | |
116 | test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly>(); // copy construction |
117 | test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); |
118 | test_pair_rv<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, true, false>(); |
119 | |
120 | test_pair_rv<CopyOnly, CopyOnly>(); |
121 | test_pair_rv<CopyOnly, CopyOnly&>(); |
122 | test_pair_rv<CopyOnly, CopyOnly&&>(); |
123 | |
124 | test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>(); |
125 | test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>(); |
126 | test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>(); |
127 | |
128 | test_pair_rv<NonCopyable, NonCopyable, false>(); |
129 | test_pair_rv<NonCopyable, NonCopyable&, false>(); |
130 | test_pair_rv<NonCopyable, NonCopyable&&, false>(); |
131 | test_pair_rv<NonCopyable, const NonCopyable&, false>(); |
132 | test_pair_rv<NonCopyable, const NonCopyable&&, false>(); |
133 | } |
134 | { // Test construction of references |
135 | test_pair_rv<NonCopyable&, NonCopyable&>(); |
136 | test_pair_rv<NonCopyable&, NonCopyable&&>(); |
137 | test_pair_rv<NonCopyable&, NonCopyable const&, false>(); |
138 | test_pair_rv<NonCopyable const&, NonCopyable&&>(); |
139 | test_pair_rv<NonCopyable&&, NonCopyable&&>(); |
140 | |
141 | test_pair_rv<ConvertingType&, int, false>(); |
142 | test_pair_rv<ExplicitTypes::ConvertingType&, int, false>(); |
143 | // Unfortunately the below conversions are allowed and create dangling |
144 | // references. |
145 | //test_pair_rv<ConvertingType&&, int>(); |
146 | //test_pair_rv<ConvertingType const&, int>(); |
147 | //test_pair_rv<ConvertingType const&&, int>(); |
148 | // But these are not because the converting constructor is explicit. |
149 | test_pair_rv<ExplicitTypes::ConvertingType&&, int, false>(); |
150 | test_pair_rv<ExplicitTypes::ConvertingType const&, int, false>(); |
151 | test_pair_rv<ExplicitTypes::ConvertingType const&&, int, false>(); |
152 | } |
153 | { |
154 | test_pair_rv<AllCtors, int, false>(); |
155 | test_pair_rv<ExplicitTypes::AllCtors, int, false>(); |
156 | test_pair_rv<ConvertingType, int>(); |
157 | test_pair_rv<ExplicitTypes::ConvertingType, int, true, false>(); |
158 | |
159 | test_pair_rv<ConvertingType, int>(); |
160 | test_pair_rv<ConvertingType, ConvertingType>(); |
161 | test_pair_rv<ConvertingType, ConvertingType const&>(); |
162 | test_pair_rv<ConvertingType, ConvertingType&>(); |
163 | test_pair_rv<ConvertingType, ConvertingType&&>(); |
164 | |
165 | test_pair_rv<ExplicitTypes::ConvertingType, int, true, false>(); |
166 | test_pair_rv<ExplicitTypes::ConvertingType, int&, true, false>(); |
167 | test_pair_rv<ExplicitTypes::ConvertingType, const int&, true, false>(); |
168 | test_pair_rv<ExplicitTypes::ConvertingType, int&&, true, false>(); |
169 | test_pair_rv<ExplicitTypes::ConvertingType, const int&&, true, false>(); |
170 | |
171 | test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType>(); |
172 | test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType const&, true, false>(); |
173 | test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&, true, false>(); |
174 | test_pair_rv<ExplicitTypes::ConvertingType, ExplicitTypes::ConvertingType&&, true, false>(); |
175 | } |
176 | { |
177 | // When constructing a pair containing a reference, we only bind the |
178 | // reference, so it doesn't matter whether the type is or isn't |
179 | // copy/move constructible. |
180 | { |
181 | using P1 = std::pair<NotCopyOrMoveConstructible&, long>; |
182 | using P2 = std::pair<NotCopyOrMoveConstructible&, int>; |
183 | static_assert(std::is_constructible<P1, P2&&>::value, "" ); |
184 | |
185 | NotCopyOrMoveConstructible obj; |
186 | P2 p2{obj, 3}; |
187 | P1 p1(std::move(p2)); |
188 | assert(&p1.first == &obj); |
189 | assert(&p2.first == &obj); |
190 | } |
191 | { |
192 | using P1 = std::pair<NotCopyOrMoveConstructible&&, long>; |
193 | using P2 = std::pair<NotCopyOrMoveConstructible&&, int>; |
194 | static_assert(std::is_constructible<P1, P2&&>::value, "" ); |
195 | |
196 | NotCopyOrMoveConstructible obj; |
197 | P2 p2{std::move(obj), 3}; |
198 | P1 p1(std::move(p2)); |
199 | assert(&p1.first == &obj); |
200 | assert(&p2.first == &obj); |
201 | } |
202 | } |
203 | { |
204 | // Make sure we can't move-construct from a pair containing a reference |
205 | // if that type isn't copy-constructible (since otherwise we'd be stealing |
206 | // the object through the reference). |
207 | using P1 = std::pair<NonCopyConstructible, long>; |
208 | using P2 = std::pair<NonCopyConstructible&, int>; |
209 | static_assert(!std::is_constructible<P1, P2&&>::value, "" ); |
210 | } |
211 | #if TEST_STD_VER > 11 |
212 | { // explicit constexpr test |
213 | constexpr std::pair<int, int> p1(42, 43); |
214 | constexpr std::pair<ExplicitT, ExplicitT> p2(std::move(p1)); |
215 | static_assert(p2.first.value == 42, "" ); |
216 | static_assert(p2.second.value == 43, "" ); |
217 | } |
218 | { // implicit constexpr test |
219 | constexpr std::pair<int, int> p1(42, 43); |
220 | constexpr std::pair<ImplicitT, ImplicitT> p2 = std::move(p1); |
221 | static_assert(p2.first.value == 42, "" ); |
222 | static_assert(p2.second.value == 43, "" ); |
223 | } |
224 | #endif |
225 | |
226 | return 0; |
227 | } |
228 | |