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 | // explicit(see-below) constexpr pair(const pair<U, V>& p); |
17 | |
18 | #include <utility> |
19 | #include <cassert> |
20 | |
21 | #include "archetypes.h" |
22 | #include "test_convertible.h" |
23 | |
24 | #include "test_macros.h" |
25 | using namespace ImplicitTypes; // Get implicitly archetypes |
26 | |
27 | template <class T1, class U1, bool CanCopy = true, bool CanConvert = CanCopy> |
28 | TEST_CONSTEXPR_CXX20 void test_pair_const() { |
29 | using P1 = std::pair<T1, int>; |
30 | using P2 = std::pair<int, T1>; |
31 | using UP1 = std::pair<U1, int> const&; |
32 | using UP2 = std::pair<int, U1> const&; |
33 | static_assert(std::is_constructible<P1, UP1>::value == CanCopy, "" ); |
34 | static_assert(test_convertible<P1, UP1>() == CanConvert, "" ); |
35 | static_assert(std::is_constructible<P2, UP2>::value == CanCopy, "" ); |
36 | static_assert(test_convertible<P2, UP2>() == CanConvert, "" ); |
37 | } |
38 | |
39 | template <class T, class U> |
40 | struct DPair : public std::pair<T, U> { |
41 | using Base = std::pair<T, U>; |
42 | using Base::Base; |
43 | }; |
44 | |
45 | struct ExplicitT { |
46 | constexpr explicit ExplicitT(int x) : value(x) {} |
47 | constexpr explicit ExplicitT(ExplicitT const& o) : value(o.value) {} |
48 | int value; |
49 | }; |
50 | |
51 | struct ImplicitT { |
52 | constexpr ImplicitT(int x) : value(x) {} |
53 | constexpr ImplicitT(ImplicitT const& o) : value(o.value) {} |
54 | int value; |
55 | }; |
56 | |
57 | TEST_CONSTEXPR_CXX20 bool test() { |
58 | { |
59 | typedef std::pair<int, int> P1; |
60 | typedef std::pair<double, long> P2; |
61 | const P1 p1(3, 4); |
62 | const P2 p2 = p1; |
63 | assert(p2.first == 3); |
64 | assert(p2.second == 4); |
65 | } |
66 | { |
67 | // We allow derived types to use this constructor |
68 | using P1 = DPair<long, long>; |
69 | using P2 = std::pair<int, int>; |
70 | P1 p1(42, 101); |
71 | P2 p2(p1); |
72 | assert(p2.first == 42); |
73 | assert(p2.second == 101); |
74 | } |
75 | { |
76 | test_pair_const<AllCtors, AllCtors>(); // copy construction |
77 | test_pair_const<AllCtors, AllCtors&>(); |
78 | test_pair_const<AllCtors, AllCtors&&>(); |
79 | test_pair_const<AllCtors, const AllCtors&>(); |
80 | test_pair_const<AllCtors, const AllCtors&&>(); |
81 | |
82 | test_pair_const<ExplicitTypes::AllCtors, |
83 | ExplicitTypes::AllCtors>(); // copy construction |
84 | test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&, true, |
85 | false>(); |
86 | test_pair_const<ExplicitTypes::AllCtors, ExplicitTypes::AllCtors&&, true, |
87 | false>(); |
88 | test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&, |
89 | true, false>(); |
90 | test_pair_const<ExplicitTypes::AllCtors, const ExplicitTypes::AllCtors&&, |
91 | true, false>(); |
92 | |
93 | test_pair_const<MoveOnly, MoveOnly, false>(); // copy construction |
94 | test_pair_const<MoveOnly, MoveOnly&, false>(); |
95 | test_pair_const<MoveOnly, MoveOnly&&, false>(); |
96 | |
97 | test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly, |
98 | false>(); // copy construction |
99 | test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&, false>(); |
100 | test_pair_const<ExplicitTypes::MoveOnly, ExplicitTypes::MoveOnly&&, |
101 | false>(); |
102 | |
103 | test_pair_const<CopyOnly, CopyOnly>(); |
104 | test_pair_const<CopyOnly, CopyOnly&>(); |
105 | test_pair_const<CopyOnly, CopyOnly&&>(); |
106 | |
107 | test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>(); |
108 | test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, |
109 | false>(); |
110 | test_pair_const<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, |
111 | false>(); |
112 | |
113 | test_pair_const<NonCopyable, NonCopyable, false>(); |
114 | test_pair_const<NonCopyable, NonCopyable&, false>(); |
115 | test_pair_const<NonCopyable, NonCopyable&&, false>(); |
116 | test_pair_const<NonCopyable, const NonCopyable&, false>(); |
117 | test_pair_const<NonCopyable, const NonCopyable&&, false>(); |
118 | } |
119 | |
120 | { // Test construction of references |
121 | test_pair_const<NonCopyable&, NonCopyable&>(); |
122 | test_pair_const<NonCopyable&, NonCopyable&&>(); |
123 | test_pair_const<NonCopyable&, NonCopyable const&, false>(); |
124 | test_pair_const<NonCopyable const&, NonCopyable&&>(); |
125 | test_pair_const<NonCopyable&&, NonCopyable&&, false>(); |
126 | |
127 | test_pair_const<ConvertingType&, int, false>(); |
128 | test_pair_const<ExplicitTypes::ConvertingType&, int, false>(); |
129 | // Unfortunately the below conversions are allowed and create dangling |
130 | // references. |
131 | //test_pair_const<ConvertingType&&, int>(); |
132 | //test_pair_const<ConvertingType const&, int>(); |
133 | //test_pair_const<ConvertingType const&&, int>(); |
134 | // But these are not because the converting constructor is explicit. |
135 | test_pair_const<ExplicitTypes::ConvertingType&&, int, false>(); |
136 | test_pair_const<ExplicitTypes::ConvertingType const&, int, false>(); |
137 | test_pair_const<ExplicitTypes::ConvertingType const&&, int, false>(); |
138 | } |
139 | { |
140 | test_pair_const<AllCtors, int, false>(); |
141 | test_pair_const<ExplicitTypes::AllCtors, int, false>(); |
142 | test_pair_const<ConvertingType, int>(); |
143 | test_pair_const<ExplicitTypes::ConvertingType, int, true, false>(); |
144 | |
145 | test_pair_const<ConvertingType, int>(); |
146 | test_pair_const<ConvertingType, ConvertingType>(); |
147 | test_pair_const<ConvertingType, ConvertingType const&>(); |
148 | test_pair_const<ConvertingType, ConvertingType&>(); |
149 | test_pair_const<ConvertingType, ConvertingType&&>(); |
150 | |
151 | test_pair_const<ExplicitTypes::ConvertingType, int, true, false>(); |
152 | test_pair_const<ExplicitTypes::ConvertingType, int&, true, false>(); |
153 | test_pair_const<ExplicitTypes::ConvertingType, const int&, true, false>(); |
154 | test_pair_const<ExplicitTypes::ConvertingType, int&&, true, false>(); |
155 | test_pair_const<ExplicitTypes::ConvertingType, const int&&, true, false>(); |
156 | |
157 | test_pair_const<ExplicitTypes::ConvertingType, |
158 | ExplicitTypes::ConvertingType>(); |
159 | test_pair_const<ExplicitTypes::ConvertingType, |
160 | ExplicitTypes::ConvertingType const&, true, false>(); |
161 | test_pair_const<ExplicitTypes::ConvertingType, |
162 | ExplicitTypes::ConvertingType&, true, false>(); |
163 | test_pair_const<ExplicitTypes::ConvertingType, |
164 | ExplicitTypes::ConvertingType&&, true, false>(); |
165 | } |
166 | #if TEST_STD_VER > 11 |
167 | { |
168 | typedef std::pair<int, int> P1; |
169 | typedef std::pair<double, long> P2; |
170 | constexpr P1 p1(3, 4); |
171 | constexpr P2 p2 = p1; |
172 | static_assert(p2.first == 3, "" ); |
173 | static_assert(p2.second == 4, "" ); |
174 | } |
175 | { |
176 | using P1 = std::pair<int, int>; |
177 | using P2 = std::pair<ExplicitT, ExplicitT>; |
178 | constexpr P1 p1(42, 101); |
179 | constexpr P2 p2(p1); |
180 | static_assert(p2.first.value == 42, "" ); |
181 | static_assert(p2.second.value == 101, "" ); |
182 | } |
183 | { |
184 | using P1 = std::pair<int, int>; |
185 | using P2 = std::pair<ImplicitT, ImplicitT>; |
186 | constexpr P1 p1(42, 101); |
187 | constexpr P2 p2 = p1; |
188 | static_assert(p2.first.value == 42, "" ); |
189 | static_assert(p2.second.value == 101, "" ); |
190 | } |
191 | #endif |
192 | return true; |
193 | } |
194 | |
195 | int main(int, char**) { |
196 | test(); |
197 | #if TEST_STD_VER >= 20 |
198 | static_assert(test()); |
199 | #endif |
200 | |
201 | return 0; |
202 | } |
203 | |