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
f_void_1(int i)29 void f_void_1(int i)
30 {
31 count += i;
32 }
33
34 struct A_void_1
35 {
operator ()A_void_136 void operator()(int i)
37 {
38 count += i;
39 }
40
mem1A_void_141 void mem1() {++count;}
mem2A_void_142 void mem2() const {count += 2;}
43 };
44
45 void
test_void_1()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_void_1, _1)(i);
54 assert(count == save_count + 2);
55 save_count = count;
56 }
57 {
58 int i = 2;
59 std::bind(f_void_1, 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(fp, _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(fp, 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(a0, _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(a0, 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(fp, _1)(a);
98 assert(count == save_count+1);
99 save_count = count;
100 A_void_1* ap = &a;
101 std::bind(fp, _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(fp, a)();
109 assert(count == save_count+1);
110 save_count = count;
111 A_void_1* ap = &a;
112 std::bind(fp, 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(fp, _1)(a);
121 assert(count == save_count+2);
122 save_count = count;
123 A_void_1* ap = &a;
124 std::bind(fp, _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(fp, a)();
132 assert(count == save_count+2);
133 save_count = count;
134 A_void_1* ap = &a;
135 std::bind(fp, ap)();
136 assert(count == save_count+2);
137 save_count = count;
138 }
139 }
140
141 // 1 arg, return int
142
f_int_1(int i)143 TEST_CONSTEXPR_CXX20 int f_int_1(int i) {
144 return i + 1;
145 }
146
147 struct A_int_1 {
A_int_1A_int_1148 TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {}
operator ()A_int_1149 TEST_CONSTEXPR_CXX20 int operator()(int i) {
150 return i - 1;
151 }
152
mem1A_int_1153 TEST_CONSTEXPR_CXX20 int mem1() { return 3; }
mem2A_int_1154 TEST_CONSTEXPR_CXX20 int mem2() const { return 4; }
155 int data_;
156 };
157
test_int_1()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(&A_int_1::data_, _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(&A_int_1::data_, _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
f_void_2(int i,int j)216 void f_void_2(int i, int j)
217 {
218 count += i+j;
219 }
220
221 struct A_void_2
222 {
operator ()A_void_2223 void operator()(int i, int j)
224 {
225 count += i+j;
226 }
227
mem1A_void_2228 void mem1(int i) {count += i;}
mem2A_void_2229 void mem2(int i) const {count += i;}
230 };
231
232 void
test_void_2()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_void_2, _1, _2)(i, j);
242 assert(count == save_count+5);
243 save_count = count;
244 std::bind(f_void_2, i, _1)(j);
245 assert(count == save_count+5);
246 save_count = count;
247 std::bind(f_void_2, i, j)();
248 assert(count == save_count+5);
249 save_count = count;
250 }
251 // member function pointer
252 {
253 int j = 3;
254 std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), j);
255 assert(count == save_count+3);
256 save_count = count;
257 std::bind(&A_void_2::mem1, _2, _1)(j, A_void_2());
258 assert(count == save_count+3);
259 save_count = count;
260 }
261 }
262
263 struct ConstQualifiedMemberFunction {
fooConstQualifiedMemberFunction264 TEST_CONSTEXPR_CXX20 bool foo(unsigned long long) const {
265 return true;
266 }
267 };
268
test_const_qualified_member()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
test_many_args()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, _4, _3, _2, _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
main(int,char **)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