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