1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <functional>
11
12// template<CopyConstructible Fn, CopyConstructible... Types>
13//   unspecified bind(Fn, Types...);
14// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
15//   unspecified bind(Fn, Types...);
16
17#include <stdio.h>
18
19#include <functional>
20#include <cassert>
21
22int count = 0;
23
24// 1 arg, return void
25
26void f_void_1(int i)
27{
28    count += i;
29}
30
31struct A_void_1
32{
33    void operator()(int i)
34    {
35        count += i;
36    }
37
38    void mem1() {++count;}
39    void mem2() const {count += 2;}
40};
41
42void
43test_void_1()
44{
45    using namespace std::placeholders;
46    int save_count = count;
47    // function
48    {
49    std::bind(f_void_1, _1)(2);
50    assert(count == save_count + 2);
51    save_count = count;
52    }
53    {
54    std::bind(f_void_1, 2)();
55    assert(count == save_count + 2);
56    save_count = count;
57    }
58    // function pointer
59    {
60    void (*fp)(int) = f_void_1;
61    std::bind(fp, _1)(3);
62    assert(count == save_count+3);
63    save_count = count;
64    }
65    {
66    void (*fp)(int) = f_void_1;
67    std::bind(fp, 3)();
68    assert(count == save_count+3);
69    save_count = count;
70    }
71    // functor
72    {
73    A_void_1 a0;
74    std::bind(a0, _1)(4);
75    assert(count == save_count+4);
76    save_count = count;
77    }
78    {
79    A_void_1 a0;
80    std::bind(a0, 4)();
81    assert(count == save_count+4);
82    save_count = count;
83    }
84    // member function pointer
85    {
86    void (A_void_1::*fp)() = &A_void_1::mem1;
87    std::bind(fp, _1)(A_void_1());
88    assert(count == save_count+1);
89    save_count = count;
90    A_void_1 a;
91    std::bind(fp, _1)(&a);
92    assert(count == save_count+1);
93    save_count = count;
94    }
95    {
96    void (A_void_1::*fp)() = &A_void_1::mem1;
97    std::bind(fp, A_void_1())();
98    assert(count == save_count+1);
99    save_count = count;
100    A_void_1 a;
101    std::bind(fp, &a)();
102    assert(count == save_count+1);
103    save_count = count;
104    }
105    // const member function pointer
106    {
107    void (A_void_1::*fp)() const = &A_void_1::mem2;
108    std::bind(fp, _1)(A_void_1());
109    assert(count == save_count+2);
110    save_count = count;
111    A_void_1 a;
112    std::bind(fp, _1)(&a);
113    assert(count == save_count+2);
114    save_count = count;
115    }
116    {
117    void (A_void_1::*fp)() const = &A_void_1::mem2;
118    std::bind(fp, A_void_1())();
119    assert(count == save_count+2);
120    save_count = count;
121    A_void_1 a;
122    std::bind(fp, &a)();
123    assert(count == save_count+2);
124    save_count = count;
125    }
126}
127
128// 1 arg, return int
129
130int f_int_1(int i)
131{
132    return i + 1;
133}
134
135struct A_int_1
136{
137    A_int_1() : data_(5) {}
138    int operator()(int i)
139    {
140        return i - 1;
141    }
142
143    int mem1() {return 3;}
144    int mem2() const {return 4;}
145    int data_;
146};
147
148void
149test_int_1()
150{
151    using namespace std::placeholders;
152    // function
153    {
154    assert(std::bind(f_int_1, _1)(2) == 3);
155    assert(std::bind(f_int_1, 2)() == 3);
156    }
157    // function pointer
158    {
159    int (*fp)(int) = f_int_1;
160    assert(std::bind(fp, _1)(3) == 4);
161    assert(std::bind(fp, 3)() == 4);
162    }
163    // functor
164    {
165    assert(std::bind(A_int_1(), _1)(4) == 3);
166    assert(std::bind(A_int_1(), 4)() == 3);
167    }
168    // member function pointer
169    {
170    assert(std::bind(&A_int_1::mem1, _1)(A_int_1()) == 3);
171    assert(std::bind(&A_int_1::mem1, A_int_1())() == 3);
172    A_int_1 a;
173    assert(std::bind(&A_int_1::mem1, _1)(&a) == 3);
174    assert(std::bind(&A_int_1::mem1, &a)() == 3);
175    }
176    // const member function pointer
177    {
178    assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4);
179    assert(std::bind(&A_int_1::mem2, A_int_1())() == 4);
180    A_int_1 a;
181    assert(std::bind(&A_int_1::mem2, _1)(&a) == 4);
182    assert(std::bind(&A_int_1::mem2, &a)() == 4);
183    }
184    // member data pointer
185    {
186    assert(std::bind(&A_int_1::data_, _1)(A_int_1()) == 5);
187    assert(std::bind(&A_int_1::data_, A_int_1())() == 5);
188    A_int_1 a;
189    assert(std::bind(&A_int_1::data_, _1)(a) == 5);
190    std::bind(&A_int_1::data_, _1)(a) = 6;
191    assert(std::bind(&A_int_1::data_, _1)(a) == 6);
192    assert(std::bind(&A_int_1::data_, _1)(&a) == 6);
193    std::bind(&A_int_1::data_, _1)(&a) = 7;
194    assert(std::bind(&A_int_1::data_, _1)(&a) == 7);
195    }
196}
197
198// 2 arg, return void
199
200void f_void_2(int i, int j)
201{
202    count += i+j;
203}
204
205struct A_void_2
206{
207    void operator()(int i, int j)
208    {
209        count += i+j;
210    }
211
212    void mem1(int i) {count += i;}
213    void mem2(int i) const {count += i;}
214};
215
216void
217test_void_2()
218{
219    using namespace std::placeholders;
220    int save_count = count;
221    // function
222    {
223    std::bind(f_void_2, _1, _2)(2, 3);
224    assert(count == save_count+5);
225    save_count = count;
226    std::bind(f_void_2, 2, _1)(3);
227    assert(count == save_count+5);
228    save_count = count;
229    std::bind(f_void_2, 2, 3)();
230    assert(count == save_count+5);
231    save_count = count;
232    }
233    // member function pointer
234    {
235    std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), 3);
236    assert(count == save_count+3);
237    save_count = count;
238    std::bind(&A_void_2::mem1, _2, _1)(3, A_void_2());
239    assert(count == save_count+3);
240    save_count = count;
241    }
242}
243
244int f_nested(int i)
245{
246    return i+1;
247}
248
249int g_nested(int i)
250{
251    return i*10;
252}
253
254void test_nested()
255{
256    using namespace std::placeholders;
257    assert(std::bind(f_nested, std::bind(g_nested, _1))(3) == 31);
258}
259
260int main()
261{
262    test_void_1();
263    test_int_1();
264    test_void_2();
265    test_nested();
266}
267