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