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