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 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
133TEST_CONSTEXPR_CXX20 int f_int_1(int i) {
134 return i + 1;
135}
136
137struct 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
148TEST_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
199void f_void_2(int i, int j)
200{
201 count += i+j;
202}
203
204struct 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
215void
216test_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
243TEST_CONSTEXPR_CXX20 int f_nested(int i) {
244 return i+1;
245}
246
247TEST_CONSTEXPR_CXX20 int g_nested(int i) {
248 return i*10;
249}
250
251TEST_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
257TEST_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
265int 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

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