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 | // <functional> |
12 | |
13 | // template<CopyConstructible Fn, CopyConstructible... Types> |
14 | // unspecified bind(Fn, Types...); // constexpr since C++20 |
15 | // template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> |
16 | // unspecified bind(Fn, Types...); // constexpr since C++20 |
17 | |
18 | #include <stdio.h> |
19 | |
20 | #include <functional> |
21 | #include <cassert> |
22 | |
23 | #include "test_macros.h" |
24 | |
25 | int count = 0; |
26 | |
27 | // 1 arg, return void |
28 | |
29 | void f_void_1(int i) |
30 | { |
31 | count += i; |
32 | } |
33 | |
34 | struct A_void_1 |
35 | { |
36 | void operator()(int i) |
37 | { |
38 | count += i; |
39 | } |
40 | |
41 | void mem1() {++count;} |
42 | void mem2() const {count += 2;} |
43 | }; |
44 | |
45 | void |
46 | test_void_1() |
47 | { |
48 | using namespace std::placeholders; |
49 | int save_count = count; |
50 | // function |
51 | { |
52 | int i = 2; |
53 | std::bind(f&: f_void_1, args: _1)(i); |
54 | assert(count == save_count + 2); |
55 | save_count = count; |
56 | } |
57 | { |
58 | int i = 2; |
59 | std::bind(f&: f_void_1, args&: i)(); |
60 | assert(count == save_count + 2); |
61 | save_count = count; |
62 | } |
63 | // function pointer |
64 | { |
65 | void (*fp)(int) = f_void_1; |
66 | int i = 3; |
67 | std::bind(f&: fp, args: _1)(i); |
68 | assert(count == save_count+3); |
69 | save_count = count; |
70 | } |
71 | { |
72 | void (*fp)(int) = f_void_1; |
73 | int i = 3; |
74 | std::bind(f&: fp, args&: i)(); |
75 | assert(count == save_count+3); |
76 | save_count = count; |
77 | } |
78 | // functor |
79 | { |
80 | A_void_1 a0; |
81 | int i = 4; |
82 | std::bind(f&: a0, args: _1)(i); |
83 | assert(count == save_count+4); |
84 | save_count = count; |
85 | } |
86 | { |
87 | A_void_1 a0; |
88 | int i = 4; |
89 | std::bind(f&: a0, args&: i)(); |
90 | assert(count == save_count+4); |
91 | save_count = count; |
92 | } |
93 | // member function pointer |
94 | { |
95 | void (A_void_1::*fp)() = &A_void_1::mem1; |
96 | A_void_1 a; |
97 | std::bind(f&: fp, args: _1)(a); |
98 | assert(count == save_count+1); |
99 | save_count = count; |
100 | A_void_1* ap = &a; |
101 | std::bind(f&: fp, args: _1)(ap); |
102 | assert(count == save_count+1); |
103 | save_count = count; |
104 | } |
105 | { |
106 | void (A_void_1::*fp)() = &A_void_1::mem1; |
107 | A_void_1 a; |
108 | std::bind(f&: fp, args&: a)(); |
109 | assert(count == save_count+1); |
110 | save_count = count; |
111 | A_void_1* ap = &a; |
112 | std::bind(f&: fp, args&: ap)(); |
113 | assert(count == save_count+1); |
114 | save_count = count; |
115 | } |
116 | // const member function pointer |
117 | { |
118 | void (A_void_1::*fp)() const = &A_void_1::mem2; |
119 | A_void_1 a; |
120 | std::bind(f&: fp, args: _1)(a); |
121 | assert(count == save_count+2); |
122 | save_count = count; |
123 | A_void_1* ap = &a; |
124 | std::bind(f&: fp, args: _1)(ap); |
125 | assert(count == save_count+2); |
126 | save_count = count; |
127 | } |
128 | { |
129 | void (A_void_1::*fp)() const = &A_void_1::mem2; |
130 | A_void_1 a; |
131 | std::bind(f&: fp, args&: a)(); |
132 | assert(count == save_count+2); |
133 | save_count = count; |
134 | A_void_1* ap = &a; |
135 | std::bind(f&: fp, args&: ap)(); |
136 | assert(count == save_count+2); |
137 | save_count = count; |
138 | } |
139 | } |
140 | |
141 | // 1 arg, return int |
142 | |
143 | TEST_CONSTEXPR_CXX20 int f_int_1(int i) { |
144 | return i + 1; |
145 | } |
146 | |
147 | struct A_int_1 { |
148 | TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {} |
149 | TEST_CONSTEXPR_CXX20 int operator()(int i) { |
150 | return i - 1; |
151 | } |
152 | |
153 | TEST_CONSTEXPR_CXX20 int mem1() { return 3; } |
154 | TEST_CONSTEXPR_CXX20 int mem2() const { return 4; } |
155 | int data_; |
156 | }; |
157 | |
158 | TEST_CONSTEXPR_CXX20 bool test_int_1() { |
159 | using namespace std::placeholders; |
160 | // function |
161 | { |
162 | int i = 2; |
163 | assert(std::bind(f_int_1, _1)(i) == 3); |
164 | assert(std::bind(f_int_1, i)() == 3); |
165 | } |
166 | // function pointer |
167 | { |
168 | int (*fp)(int) = f_int_1; |
169 | int i = 3; |
170 | assert(std::bind(fp, _1)(i) == 4); |
171 | assert(std::bind(fp, i)() == 4); |
172 | } |
173 | // functor |
174 | { |
175 | int i = 4; |
176 | assert(std::bind(A_int_1(), _1)(i) == 3); |
177 | assert(std::bind(A_int_1(), i)() == 3); |
178 | } |
179 | // member function pointer |
180 | { |
181 | A_int_1 a; |
182 | assert(std::bind(&A_int_1::mem1, _1)(a) == 3); |
183 | assert(std::bind(&A_int_1::mem1, a)() == 3); |
184 | A_int_1* ap = &a; |
185 | assert(std::bind(&A_int_1::mem1, _1)(ap) == 3); |
186 | assert(std::bind(&A_int_1::mem1, ap)() == 3); |
187 | } |
188 | // const member function pointer |
189 | { |
190 | A_int_1 a; |
191 | assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4); |
192 | assert(std::bind(&A_int_1::mem2, A_int_1())() == 4); |
193 | A_int_1* ap = &a; |
194 | assert(std::bind(&A_int_1::mem2, _1)(ap) == 4); |
195 | assert(std::bind(&A_int_1::mem2, ap)() == 4); |
196 | } |
197 | // member data pointer |
198 | { |
199 | A_int_1 a; |
200 | assert(std::bind(&A_int_1::data_, _1)(a) == 5); |
201 | assert(std::bind(&A_int_1::data_, a)() == 5); |
202 | A_int_1* ap = &a; |
203 | assert(std::bind(&A_int_1::data_, _1)(a) == 5); |
204 | std::bind(f: &A_int_1::data_, args: _1)(a) = 6; |
205 | assert(std::bind(&A_int_1::data_, _1)(a) == 6); |
206 | assert(std::bind(&A_int_1::data_, _1)(ap) == 6); |
207 | std::bind(f: &A_int_1::data_, args: _1)(ap) = 7; |
208 | assert(std::bind(&A_int_1::data_, _1)(ap) == 7); |
209 | } |
210 | |
211 | return true; |
212 | } |
213 | |
214 | // 2 arg, return void |
215 | |
216 | void f_void_2(int i, int j) |
217 | { |
218 | count += i+j; |
219 | } |
220 | |
221 | struct A_void_2 |
222 | { |
223 | void operator()(int i, int j) |
224 | { |
225 | count += i+j; |
226 | } |
227 | |
228 | void mem1(int i) {count += i;} |
229 | void mem2(int i) const {count += i;} |
230 | }; |
231 | |
232 | void |
233 | test_void_2() |
234 | { |
235 | using namespace std::placeholders; |
236 | int save_count = count; |
237 | // function |
238 | { |
239 | int i = 2; |
240 | int j = 3; |
241 | std::bind(f&: f_void_2, args: _1, args: _2)(i, j); |
242 | assert(count == save_count+5); |
243 | save_count = count; |
244 | std::bind(f&: f_void_2, args&: i, args: _1)(j); |
245 | assert(count == save_count+5); |
246 | save_count = count; |
247 | std::bind(f&: f_void_2, args&: i, args&: j)(); |
248 | assert(count == save_count+5); |
249 | save_count = count; |
250 | } |
251 | // member function pointer |
252 | { |
253 | int j = 3; |
254 | std::bind(f: &A_void_2::mem1, args: _1, args: _2)(A_void_2(), j); |
255 | assert(count == save_count+3); |
256 | save_count = count; |
257 | std::bind(f: &A_void_2::mem1, args: _2, args: _1)(j, A_void_2()); |
258 | assert(count == save_count+3); |
259 | save_count = count; |
260 | } |
261 | } |
262 | |
263 | struct ConstQualifiedMemberFunction { |
264 | TEST_CONSTEXPR_CXX20 bool foo(unsigned long long) const { |
265 | return true; |
266 | } |
267 | }; |
268 | |
269 | TEST_CONSTEXPR_CXX20 bool test_const_qualified_member() { |
270 | using namespace std; |
271 | using namespace std::placeholders; |
272 | const auto f = bind(&ConstQualifiedMemberFunction::foo, _1, 0UL); |
273 | const ConstQualifiedMemberFunction n = ConstQualifiedMemberFunction{}; |
274 | bool b = f(n); |
275 | assert(b); |
276 | return true; |
277 | } |
278 | |
279 | TEST_CONSTEXPR_CXX20 bool test_many_args() { |
280 | using namespace std::placeholders; |
281 | auto f = [](int& a, char&, float&, long&) -> int& { return a; }; |
282 | auto bound = std::bind(f&: f, args: _4, args: _3, args: _2, args: _1); |
283 | int a = 3; char b = '2'; float c = 1.0f; long d = 0l; |
284 | int& result = bound(d, c, b, a); |
285 | assert(&result == &a); |
286 | return true; |
287 | } |
288 | |
289 | int main(int, char**) { |
290 | test_void_1(); |
291 | test_int_1(); |
292 | test_void_2(); |
293 | test_const_qualified_member(); |
294 | test_many_args(); |
295 | |
296 | // The other tests are not constexpr-friendly since they need to use a global variable |
297 | #if TEST_STD_VER >= 20 |
298 | static_assert(test_int_1()); |
299 | static_assert(test_const_qualified_member()); |
300 | static_assert(test_many_args()); |
301 | #endif |
302 | |
303 | return 0; |
304 | } |
305 | |