1// Boost.TypeErasure library
2//
3// Copyright 2011 Steven Watanabe
4//
5// Distributed under the Boost Software License Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// $Id$
10
11#include <boost/type_erasure/any.hpp>
12#include <boost/type_erasure/builtin.hpp>
13#include <boost/type_erasure/callable.hpp>
14#include <boost/type_erasure/any_cast.hpp>
15#include <boost/type_erasure/tuple.hpp>
16#include <boost/mpl/vector.hpp>
17#include <boost/mpl/assert.hpp>
18#include <boost/type_traits/is_same.hpp>
19#include <boost/utility/result_of.hpp>
20#include <vector>
21
22#define BOOST_TEST_MAIN
23#include <boost/test/unit_test.hpp>
24
25using namespace boost::type_erasure;
26
27template<class T = _self>
28struct common : ::boost::mpl::vector<
29 copy_constructible<T>,
30 typeid_<T>
31> {};
32
33int f1_val;
34void f1() { ++f1_val; }
35
36int f2_val;
37int f2() { return ++f2_val; }
38
39BOOST_AUTO_TEST_CASE(test_void)
40{
41 typedef ::boost::mpl::vector<
42 common<>,
43 callable<void()>
44 > test_concept;
45 any<test_concept> x1(&f1);
46 f1_val = 0;
47 x1();
48 BOOST_CHECK_EQUAL(f1_val, 1);
49
50 any<test_concept> x2(&f2);
51 f2_val = 0;
52 x2();
53 BOOST_CHECK_EQUAL(f2_val, 1);
54
55 typedef ::boost::mpl::vector<
56 common<>,
57 callable<int()>
58 > test_concept_int;
59 any<test_concept_int> x3(&f2);
60 f2_val = 0;
61 int i = x3();
62 BOOST_CHECK_EQUAL(i, 1);
63 BOOST_CHECK_EQUAL(f2_val, 1);
64}
65
66BOOST_AUTO_TEST_CASE(test_void_const)
67{
68 typedef ::boost::mpl::vector<
69 common<>,
70 callable<void(), const _self>
71 > test_concept;
72 const any<test_concept> x1(&f1);
73 f1_val = 0;
74 x1();
75 BOOST_CHECK_EQUAL(f1_val, 1);
76
77 const any<test_concept> x2(&f2);
78 f2_val = 0;
79 x2();
80 BOOST_CHECK_EQUAL(f2_val, 1);
81
82 typedef ::boost::mpl::vector<
83 common<>,
84 callable<int(), const _self>
85 > test_concept_int;
86 const any<test_concept_int> x3(&f2);
87 f2_val = 0;
88 int i = x3();
89 BOOST_CHECK_EQUAL(i, 1);
90 BOOST_CHECK_EQUAL(f2_val, 1);
91}
92
93int f3_val;
94void f3(int i) { f3_val += i; }
95
96int f4_val;
97int f4(int i) { return f4_val += i; }
98
99BOOST_AUTO_TEST_CASE(test_int)
100{
101 typedef ::boost::mpl::vector<
102 common<>,
103 callable<void(int)>
104 > test_concept;
105 any<test_concept> x1(&f3);
106 f3_val = 1;
107 x1(3);
108 BOOST_CHECK_EQUAL(f3_val, 4);
109
110 any<test_concept> x2(&f4);
111 f4_val = 1;
112 x2(2);
113 BOOST_CHECK_EQUAL(f4_val, 3);
114
115 typedef ::boost::mpl::vector<
116 common<>,
117 callable<int(int)>
118 > test_concept_int;
119 any<test_concept_int> x3(&f4);
120 f4_val = 1;
121 int i = x3(4);
122 BOOST_CHECK_EQUAL(i, 5);
123 BOOST_CHECK_EQUAL(f4_val, 5);
124}
125
126BOOST_AUTO_TEST_CASE(test_int_const)
127{
128 typedef ::boost::mpl::vector<
129 common<>,
130 callable<void(int), const _self>
131 > test_concept;
132 const any<test_concept> x1(&f3);
133 f3_val = 1;
134 x1(3);
135 BOOST_CHECK_EQUAL(f3_val, 4);
136
137 const any<test_concept> x2(&f4);
138 f4_val = 1;
139 x2(2);
140 BOOST_CHECK_EQUAL(f4_val, 3);
141
142 typedef ::boost::mpl::vector<
143 common<>,
144 callable<int(int), const _self>
145 > test_concept_int;
146 const any<test_concept_int> x3(&f4);
147 f4_val = 1;
148 int i = x3(4);
149 BOOST_CHECK_EQUAL(i, 5);
150 BOOST_CHECK_EQUAL(f4_val, 5);
151}
152
153BOOST_AUTO_TEST_CASE(test_any)
154{
155 typedef ::boost::mpl::vector<
156 common<>,
157 common<_a>,
158 callable<void(_a)>
159 > test_concept;
160 tuple<test_concept, _self, _a> t1(&f3, 3);
161 any<test_concept> x1(get<0>(t&: t1));
162 f3_val = 1;
163 x1(get<1>(t&: t1));
164 BOOST_CHECK_EQUAL(f3_val, 4);
165
166 tuple<test_concept, _self, _a> t2(&f4, 2);
167 any<test_concept> x2(get<0>(t&: t2));
168 f4_val = 1;
169 x2(get<1>(t&: t2));
170 BOOST_CHECK_EQUAL(f4_val, 3);
171
172 typedef ::boost::mpl::vector<
173 common<>,
174 common<_a>,
175 callable<_a(_a)>
176 > test_concept_int;
177 tuple<test_concept_int, _self, _a> t3(&f4, 4);
178 any<test_concept_int> x3(get<0>(t&: t3));
179 f4_val = 1;
180 int i = any_cast<int>(arg: x3(get<1>(t&: t3)));
181 BOOST_CHECK_EQUAL(i, 5);
182 BOOST_CHECK_EQUAL(f4_val, 5);
183}
184
185BOOST_AUTO_TEST_CASE(test_any_const)
186{
187 typedef ::boost::mpl::vector<
188 common<>,
189 common<_a>,
190 callable<void(_a), const _self>
191 > test_concept;
192 tuple<test_concept, _self, _a> t1(&f3, 3);
193 const any<test_concept> x1(get<0>(t&: t1));
194 f3_val = 1;
195 x1(get<1>(t&: t1));
196 BOOST_CHECK_EQUAL(f3_val, 4);
197
198 tuple<test_concept, _self, _a> t2(&f4, 2);
199 const any<test_concept> x2(get<0>(t&: t2));
200 f4_val = 1;
201 x2(get<1>(t&: t2));
202 BOOST_CHECK_EQUAL(f4_val, 3);
203
204 typedef ::boost::mpl::vector<
205 common<>,
206 common<_a>,
207 callable<_a(_a), const _self>
208 > test_concept_int;
209 tuple<test_concept_int, _self, _a> t3(&f4, 4);
210 const any<test_concept_int> x3(get<0>(t&: t3));
211 f4_val = 1;
212 int i = any_cast<int>(arg: x3(get<1>(t&: t3)));
213 BOOST_CHECK_EQUAL(i, 5);
214 BOOST_CHECK_EQUAL(f4_val, 5);
215}
216
217int overload1;
218int overload2;
219int overload3;
220
221struct overloaded_function
222{
223 int operator()() const { return ++overload1; }
224 int operator()(int i) const { return overload2 += i; }
225 int operator()(short i) const { return overload3 += i; }
226};
227
228BOOST_AUTO_TEST_CASE(test_result_of)
229{
230 typedef ::boost::mpl::vector<
231 common<>,
232 common<_a>,
233 callable<void()>,
234 callable<int(int)>,
235 callable<long(_a)>
236 > test_concept;
237
238 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, void>));
239 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, int>));
240 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, long>));
241}
242
243BOOST_AUTO_TEST_CASE(test_result_of_const)
244{
245 typedef ::boost::mpl::vector<
246 common<>,
247 common<_a>,
248 callable<void(), const _self>,
249 callable<int(int), const _self>,
250 callable<long(_a), const _self>
251 > test_concept;
252
253 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>()>::type, void>));
254 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, int>));
255 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, long>));
256}
257
258BOOST_AUTO_TEST_CASE(test_overload)
259{
260 typedef ::boost::mpl::vector<
261 common<>,
262 common<_a>,
263 callable<void()>,
264 callable<void(int)>,
265 callable<void(_a)>
266 > test_concept;
267 tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3));
268 any<test_concept> f(get<0>(t));
269 any<test_concept, _a> a(get<1>(t));
270
271 overload1 = 0;
272 f();
273 BOOST_CHECK_EQUAL(overload1, 1);
274
275 overload2 = 0;
276 f(2);
277 BOOST_CHECK_EQUAL(overload2, 2);
278
279 overload3 = 0;
280 f(a);
281 BOOST_CHECK_EQUAL(overload3, 3);
282
283 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, void>));
284 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, void>));
285 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, void>));
286}
287
288BOOST_AUTO_TEST_CASE(test_overload_return)
289{
290 typedef ::boost::mpl::vector<
291 common<>,
292 common<_a>,
293 callable<int()>,
294 callable<int(int)>,
295 callable<int(_a)>
296 > test_concept;
297 tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3));
298 any<test_concept> f(get<0>(t));
299 any<test_concept, _a> a(get<1>(t));
300
301 overload1 = 0;
302 BOOST_CHECK_EQUAL(f(), 1);
303 BOOST_CHECK_EQUAL(overload1, 1);
304
305 overload2 = 0;
306 BOOST_CHECK_EQUAL(f(2), 2);
307 BOOST_CHECK_EQUAL(overload2, 2);
308
309 overload3 = 0;
310 BOOST_CHECK_EQUAL(f(a), 3);
311 BOOST_CHECK_EQUAL(overload3, 3);
312
313 //BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, int>));
314 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, int>));
315 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, int>));
316}
317
318
319BOOST_AUTO_TEST_CASE(test_overload_const)
320{
321 typedef ::boost::mpl::vector<
322 common<>,
323 common<_a>,
324 callable<void(), const _self>,
325 callable<void(int), const _self>,
326 callable<void(_a), const _self>
327 > test_concept;
328 tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3));
329 any<test_concept> f(get<0>(t));
330 any<test_concept, _a> a(get<1>(t));
331
332 overload1 = 0;
333 f();
334 BOOST_CHECK_EQUAL(overload1, 1);
335
336 overload2 = 0;
337 f(2);
338 BOOST_CHECK_EQUAL(overload2, 2);
339
340 overload3 = 0;
341 f(a);
342 BOOST_CHECK_EQUAL(overload3, 3);
343
344 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>()>::type, void>));
345 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, void>));
346 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, void>));
347}
348
349BOOST_AUTO_TEST_CASE(test_overload_return_const)
350{
351 typedef ::boost::mpl::vector<
352 common<>,
353 common<_a>,
354 callable<int(), const _self>,
355 callable<int(int), const _self>,
356 callable<int(_a), const _self>
357 > test_concept;
358 tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3));
359 any<test_concept> f(get<0>(t));
360 any<test_concept, _a> a(get<1>(t));
361
362 overload1 = 0;
363 BOOST_CHECK_EQUAL(f(), 1);
364 BOOST_CHECK_EQUAL(overload1, 1);
365
366 overload2 = 0;
367 BOOST_CHECK_EQUAL(f(2), 2);
368 BOOST_CHECK_EQUAL(overload2, 2);
369
370 overload3 = 0;
371 BOOST_CHECK_EQUAL(f(a), 3);
372 BOOST_CHECK_EQUAL(overload3, 3);
373
374 //BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, int>));
375 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, int>));
376 BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, int>));
377}
378
379struct model_ret_ref
380{
381 model_ret_ref& operator()() { return *this; }
382};
383
384BOOST_AUTO_TEST_CASE(test_ref_any_result)
385{
386 typedef ::boost::mpl::vector<
387 common<>,
388 callable<_self&()>
389 > test_concept;
390
391 any<test_concept> x1 = model_ret_ref();
392 any<test_concept, _self&> x2(x1());
393 BOOST_CHECK_EQUAL(any_cast<model_ret_ref*>(&x1), any_cast<model_ret_ref*>(&x2));
394}
395
396int f_ret_ref_val;
397int& f_ret_ref() { return f_ret_ref_val; }
398
399BOOST_AUTO_TEST_CASE(test_ref_int_result)
400{
401 typedef ::boost::mpl::vector<
402 common<>,
403 callable<int&()>
404 > test_concept;
405
406 any<test_concept> x1 = f_ret_ref;
407 int& result = x1();
408 BOOST_CHECK_EQUAL(&result, &f_ret_ref_val);
409}
410
411struct model_ret_cref
412{
413 const model_ret_cref& operator()() { return *this; }
414};
415
416BOOST_AUTO_TEST_CASE(test_cref_any_result)
417{
418 typedef ::boost::mpl::vector<
419 common<>,
420 callable<const _self&()>
421 > test_concept;
422
423 any<test_concept> x1 = model_ret_ref();
424 any<test_concept, const _self&> x2(x1());
425 BOOST_CHECK_EQUAL(any_cast<const model_ret_cref*>(&x1), any_cast<const model_ret_cref*>(&x2));
426}
427
428int f_ret_cref_val;
429const int& f_ret_cref() { return f_ret_cref_val; }
430
431BOOST_AUTO_TEST_CASE(test_cref_int_result)
432{
433 typedef ::boost::mpl::vector<
434 common<>,
435 callable<const int&()>
436 > test_concept;
437
438 any<test_concept> x1 = f_ret_cref;
439 const int& result = x1();
440 BOOST_CHECK_EQUAL(&result, &f_ret_cref_val);
441}
442
443#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
444
445int f_rv_value = 0;
446void f_rv(int&& i) { f_rv_value += i; }
447
448BOOST_AUTO_TEST_CASE(test_rvalue_int)
449{
450 typedef ::boost::mpl::vector<
451 common<>,
452 callable<void(int&&)>
453 > test_concept;
454 any<test_concept> f(&f_rv);
455
456 f_rv_value = 1;
457 f(2);
458 BOOST_CHECK_EQUAL(f_rv_value, 3);
459}
460
461BOOST_AUTO_TEST_CASE(test_rvalue_any)
462{
463 typedef ::boost::mpl::vector<
464 common<>,
465 common<_a>,
466 callable<void(_a&&)>
467 > test_concept;
468
469 tuple<test_concept, _self, _a> t1(&f_rv, 3);
470 any<test_concept> x1(get<0>(t&: t1));
471 f_rv_value = 1;
472 x1(std::move(get<1>(t&: t1)));
473 BOOST_CHECK_EQUAL(f_rv_value, 4);
474}
475
476BOOST_AUTO_TEST_CASE(test_const_rvalue_int)
477{
478 typedef ::boost::mpl::vector<
479 common<>,
480 callable<void(int&&), const _self>
481 > test_concept;
482 const any<test_concept> f(&f_rv);
483
484 f_rv_value = 1;
485 f(2);
486 BOOST_CHECK_EQUAL(f_rv_value, 3);
487}
488
489BOOST_AUTO_TEST_CASE(test_const_rvalue_any)
490{
491 typedef ::boost::mpl::vector<
492 common<>,
493 common<_a>,
494 callable<void(_a&&), const _self>
495 > test_concept;
496
497 tuple<test_concept, _self, _a> t1(&f_rv, 3);
498 const any<test_concept> x1(get<0>(t&: t1));
499 f_rv_value = 1;
500 x1(std::move(get<1>(t&: t1)));
501 BOOST_CHECK_EQUAL(f_rv_value, 4);
502}
503
504struct model_ret_rref
505{
506 model_ret_rref&& operator()() { return std::move(*this); }
507};
508
509BOOST_AUTO_TEST_CASE(test_rvalue_any_result)
510{
511 typedef ::boost::mpl::vector<
512 common<>,
513 callable<_self&&()>
514 > test_concept;
515
516 any<test_concept> x1 = model_ret_rref();
517 any<test_concept, _self&&> x2(x1());
518 BOOST_CHECK_EQUAL(any_cast<model_ret_rref*>(&x1), any_cast<model_ret_rref*>(&x2));
519}
520
521int f_ret_rv_val;
522int&& f_ret_rv() { return std::move(f_ret_rv_val); }
523
524BOOST_AUTO_TEST_CASE(test_rvalue_int_result)
525{
526 typedef ::boost::mpl::vector<
527 common<>,
528 callable<int&&()>
529 > test_concept;
530
531 any<test_concept> x1 = f_ret_rv;
532 int&& result = x1();
533 BOOST_CHECK_EQUAL(&result, &f_ret_rv_val);
534}
535
536#endif
537

source code of boost/libs/type_erasure/test/test_callable.cpp