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 std::bind(f_void_1, _1)(2);
53 assert(count == save_count + 2);
54 save_count = count;
55 }
56 {
57 std::bind(f_void_1, 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(fp, _1)(3);
65 assert(count == save_count+3);
66 save_count = count;
67 }
68 {
69 void (*fp)(int) = f_void_1;
70 std::bind(fp, 3)();
71 assert(count == save_count+3);
72 save_count = count;
73 }
74 // functor
75 {
76 A_void_1 a0;
77 std::bind(a0, _1)(4);
78 assert(count == save_count+4);
79 save_count = count;
80 }
81 {
82 A_void_1 a0;
83 std::bind(a0, 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(fp, _1)(A_void_1());
91 assert(count == save_count+1);
92 save_count = count;
93 A_void_1 a;
94 std::bind(fp, _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(fp, A_void_1())();
101 assert(count == save_count+1);
102 save_count = count;
103 A_void_1 a;
104 std::bind(fp, &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(fp, _1)(A_void_1());
112 assert(count == save_count+2);
113 save_count = count;
114 A_void_1 a;
115 std::bind(fp, _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(fp, A_void_1())();
122 assert(count == save_count+2);
123 save_count = count;
124 A_void_1 a;
125 std::bind(fp, &a)();
126 assert(count == save_count+2);
127 save_count = count;
128 }
129 }
130
131 // 1 arg, return int
132
f_int_1(int i)133 TEST_CONSTEXPR_CXX20 int f_int_1(int i) {
134 return i + 1;
135 }
136
137 struct A_int_1 {
A_int_1A_int_1138 TEST_CONSTEXPR_CXX20 A_int_1() : data_(5) {}
operator ()A_int_1139 TEST_CONSTEXPR_CXX20 int operator()(int i) {
140 return i - 1;
141 }
142
mem1A_int_1143 TEST_CONSTEXPR_CXX20 int mem1() { return 3; }
mem2A_int_1144 TEST_CONSTEXPR_CXX20 int mem2() const { return 4; }
145 int data_;
146 };
147
test_int_1()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(&A_int_1::data_, _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(&A_int_1::data_, _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
f_void_2(int i,int j)199 void f_void_2(int i, int j)
200 {
201 count += i+j;
202 }
203
204 struct A_void_2
205 {
operator ()A_void_2206 void operator()(int i, int j)
207 {
208 count += i+j;
209 }
210
mem1A_void_2211 void mem1(int i) {count += i;}
mem2A_void_2212 void mem2(int i) const {count += i;}
213 };
214
215 void
test_void_2()216 test_void_2()
217 {
218 using namespace std::placeholders;
219 int save_count = count;
220 // function
221 {
222 std::bind(f_void_2, _1, _2)(2, 3);
223 assert(count == save_count+5);
224 save_count = count;
225 std::bind(f_void_2, 2, _1)(3);
226 assert(count == save_count+5);
227 save_count = count;
228 std::bind(f_void_2, 2, 3)();
229 assert(count == save_count+5);
230 save_count = count;
231 }
232 // member function pointer
233 {
234 std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), 3);
235 assert(count == save_count+3);
236 save_count = count;
237 std::bind(&A_void_2::mem1, _2, _1)(3, A_void_2());
238 assert(count == save_count+3);
239 save_count = count;
240 }
241 }
242
f_nested(int i)243 TEST_CONSTEXPR_CXX20 int f_nested(int i) {
244 return i+1;
245 }
246
g_nested(int i)247 TEST_CONSTEXPR_CXX20 int g_nested(int i) {
248 return i*10;
249 }
250
test_nested()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
test_many_args()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, _4, _3, _2, _1);
261 assert(bound(0l, 1.0f, '2', 3) == 3);
262 return true;
263 }
264
main(int,char **)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