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
25int count = 0;
26
27// 1 arg, return void
28
29void f_void_1(int i)
30{
31 count += i;
32}
33
34struct 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
45void
46test_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
143TEST_CONSTEXPR_CXX20 int f_int_1(int i) {
144 return i + 1;
145}
146
147struct 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
158TEST_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
216void f_void_2(int i, int j)
217{
218 count += i+j;
219}
220
221struct 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
232void
233test_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
263struct ConstQualifiedMemberFunction {
264 TEST_CONSTEXPR_CXX20 bool foo(unsigned long long) const {
265 return true;
266 }
267};
268
269TEST_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
279TEST_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
289int 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

source code of libcxx/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp