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 | std::bind(f&: f_void_1, args: _1)(2); |
53 | assert(count == save_count + 2); |
54 | save_count = count; |
55 | } |
56 | { |
57 | std::bind(f&: f_void_1, args: 2)(); |
58 | assert(count == save_count + 2); |
59 | save_count = count; |
60 | } |
61 | // function pointer |
62 | { |
63 | void (*fp)(int) = f_void_1; |
64 | std::bind(f&: fp, args: _1)(3); |
65 | assert(count == save_count+3); |
66 | save_count = count; |
67 | } |
68 | { |
69 | void (*fp)(int) = f_void_1; |
70 | std::bind(f&: fp, args: 3)(); |
71 | assert(count == save_count+3); |
72 | save_count = count; |
73 | } |
74 | // functor |
75 | { |
76 | A_void_1 a0; |
77 | std::bind(f&: a0, args: _1)(4); |
78 | assert(count == save_count+4); |
79 | save_count = count; |
80 | } |
81 | { |
82 | A_void_1 a0; |
83 | std::bind(f&: a0, args: 4)(); |
84 | assert(count == save_count+4); |
85 | save_count = count; |
86 | } |
87 | // member function pointer |
88 | { |
89 | void (A_void_1::*fp)() = &A_void_1::mem1; |
90 | std::bind(f&: fp, args: _1)(A_void_1()); |
91 | assert(count == save_count+1); |
92 | save_count = count; |
93 | A_void_1 a; |
94 | std::bind(f&: fp, args: _1)(&a); |
95 | assert(count == save_count+1); |
96 | save_count = count; |
97 | } |
98 | { |
99 | void (A_void_1::*fp)() = &A_void_1::mem1; |
100 | std::bind(f&: fp, args: A_void_1())(); |
101 | assert(count == save_count+1); |
102 | save_count = count; |
103 | A_void_1 a; |
104 | std::bind(f&: fp, args: &a)(); |
105 | assert(count == save_count+1); |
106 | save_count = count; |
107 | } |
108 | // const member function pointer |
109 | { |
110 | void (A_void_1::*fp)() const = &A_void_1::mem2; |
111 | std::bind(f&: fp, args: _1)(A_void_1()); |
112 | assert(count == save_count+2); |
113 | save_count = count; |
114 | A_void_1 a; |
115 | std::bind(f&: fp, args: _1)(&a); |
116 | assert(count == save_count+2); |
117 | save_count = count; |
118 | } |
119 | { |
120 | void (A_void_1::*fp)() const = &A_void_1::mem2; |
121 | std::bind(f&: fp, args: A_void_1())(); |
122 | assert(count == save_count+2); |
123 | save_count = count; |
124 | A_void_1 a; |
125 | std::bind(f&: fp, args: &a)(); |
126 | assert(count == save_count+2); |
127 | save_count = count; |
128 | } |
129 | } |
130 | |
131 | // 1 arg, return int |
132 | |
133 | TEST_CONSTEXPR_CXX20 int f_int_1(int i) { |
134 | return i + 1; |
135 | } |
136 | |
137 | struct A_int_1 { |
138 | TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {} |
139 | TEST_CONSTEXPR_CXX20 int operator()(int i) { |
140 | return i - 1; |
141 | } |
142 | |
143 | TEST_CONSTEXPR_CXX20 int mem1() { return 3; } |
144 | TEST_CONSTEXPR_CXX20 int mem2() const { return 4; } |
145 | int data_; |
146 | }; |
147 | |
148 | TEST_CONSTEXPR_CXX20 bool test_int_1() { |
149 | using namespace std::placeholders; |
150 | // function |
151 | { |
152 | assert(std::bind(f_int_1, _1)(2) == 3); |
153 | assert(std::bind(f_int_1, 2)() == 3); |
154 | } |
155 | // function pointer |
156 | { |
157 | int (*fp)(int) = f_int_1; |
158 | assert(std::bind(fp, _1)(3) == 4); |
159 | assert(std::bind(fp, 3)() == 4); |
160 | } |
161 | // functor |
162 | { |
163 | assert(std::bind(A_int_1(), _1)(4) == 3); |
164 | assert(std::bind(A_int_1(), 4)() == 3); |
165 | } |
166 | // member function pointer |
167 | { |
168 | assert(std::bind(&A_int_1::mem1, _1)(A_int_1()) == 3); |
169 | assert(std::bind(&A_int_1::mem1, A_int_1())() == 3); |
170 | A_int_1 a; |
171 | assert(std::bind(&A_int_1::mem1, _1)(&a) == 3); |
172 | assert(std::bind(&A_int_1::mem1, &a)() == 3); |
173 | } |
174 | // const member function pointer |
175 | { |
176 | assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4); |
177 | assert(std::bind(&A_int_1::mem2, A_int_1())() == 4); |
178 | A_int_1 a; |
179 | assert(std::bind(&A_int_1::mem2, _1)(&a) == 4); |
180 | assert(std::bind(&A_int_1::mem2, &a)() == 4); |
181 | } |
182 | // member data pointer |
183 | { |
184 | assert(std::bind(&A_int_1::data_, _1)(A_int_1()) == 5); |
185 | assert(std::bind(&A_int_1::data_, A_int_1())() == 5); |
186 | A_int_1 a; |
187 | assert(std::bind(&A_int_1::data_, _1)(a) == 5); |
188 | std::bind(f: &A_int_1::data_, args: _1)(a) = 6; |
189 | assert(std::bind(&A_int_1::data_, _1)(a) == 6); |
190 | assert(std::bind(&A_int_1::data_, _1)(&a) == 6); |
191 | std::bind(f: &A_int_1::data_, args: _1)(&a) = 7; |
192 | assert(std::bind(&A_int_1::data_, _1)(&a) == 7); |
193 | } |
194 | return true; |
195 | } |
196 | |
197 | // 2 arg, return void |
198 | |
199 | void f_void_2(int i, int j) |
200 | { |
201 | count += i+j; |
202 | } |
203 | |
204 | struct A_void_2 |
205 | { |
206 | void operator()(int i, int j) |
207 | { |
208 | count += i+j; |
209 | } |
210 | |
211 | void mem1(int i) {count += i;} |
212 | void mem2(int i) const {count += i;} |
213 | }; |
214 | |
215 | void |
216 | test_void_2() |
217 | { |
218 | using namespace std::placeholders; |
219 | int save_count = count; |
220 | // function |
221 | { |
222 | std::bind(f&: f_void_2, args: _1, args: _2)(2, 3); |
223 | assert(count == save_count+5); |
224 | save_count = count; |
225 | std::bind(f&: f_void_2, args: 2, args: _1)(3); |
226 | assert(count == save_count+5); |
227 | save_count = count; |
228 | std::bind(f&: f_void_2, args: 2, args: 3)(); |
229 | assert(count == save_count+5); |
230 | save_count = count; |
231 | } |
232 | // member function pointer |
233 | { |
234 | std::bind(f: &A_void_2::mem1, args: _1, args: _2)(A_void_2(), 3); |
235 | assert(count == save_count+3); |
236 | save_count = count; |
237 | std::bind(f: &A_void_2::mem1, args: _2, args: _1)(3, A_void_2()); |
238 | assert(count == save_count+3); |
239 | save_count = count; |
240 | } |
241 | } |
242 | |
243 | TEST_CONSTEXPR_CXX20 int f_nested(int i) { |
244 | return i+1; |
245 | } |
246 | |
247 | TEST_CONSTEXPR_CXX20 int g_nested(int i) { |
248 | return i*10; |
249 | } |
250 | |
251 | TEST_CONSTEXPR_CXX20 bool test_nested() { |
252 | using namespace std::placeholders; |
253 | assert(std::bind(f_nested, std::bind(g_nested, _1))(3) == 31); |
254 | return true; |
255 | } |
256 | |
257 | TEST_CONSTEXPR_CXX20 bool test_many_args() { |
258 | using namespace std::placeholders; |
259 | auto f = [](int a, char, float, long) { return a; }; |
260 | auto bound = std::bind(f&: f, args: _4, args: _3, args: _2, args: _1); |
261 | assert(bound(0l, 1.0f, '2', 3) == 3); |
262 | return true; |
263 | } |
264 | |
265 | int main(int, char**) { |
266 | test_void_1(); |
267 | test_int_1(); |
268 | test_void_2(); |
269 | test_nested(); |
270 | |
271 | // The other tests are not constexpr-friendly since they need to use a global variable |
272 | #if TEST_STD_VER >= 20 |
273 | static_assert(test_int_1()); |
274 | static_assert(test_nested()); |
275 | #endif |
276 | |
277 | return 0; |
278 | } |
279 | |