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 | |
25 | using namespace boost::type_erasure; |
26 | |
27 | template<class T = _self> |
28 | struct common : ::boost::mpl::vector< |
29 | copy_constructible<T>, |
30 | typeid_<T> |
31 | > {}; |
32 | |
33 | int f1_val; |
34 | void f1() { ++f1_val; } |
35 | |
36 | int f2_val; |
37 | int f2() { return ++f2_val; } |
38 | |
39 | BOOST_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 | |
66 | BOOST_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 | |
93 | int f3_val; |
94 | void f3(int i) { f3_val += i; } |
95 | |
96 | int f4_val; |
97 | int f4(int i) { return f4_val += i; } |
98 | |
99 | BOOST_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 | |
126 | BOOST_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 | |
153 | BOOST_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 | |
185 | BOOST_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 | |
217 | int overload1; |
218 | int overload2; |
219 | int overload3; |
220 | |
221 | struct 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 | |
228 | BOOST_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 | |
243 | BOOST_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 | |
258 | BOOST_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 | |
288 | BOOST_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 | |
319 | BOOST_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 | |
349 | BOOST_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 | |
379 | struct model_ret_ref |
380 | { |
381 | model_ret_ref& operator()() { return *this; } |
382 | }; |
383 | |
384 | BOOST_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 | |
396 | int f_ret_ref_val; |
397 | int& f_ret_ref() { return f_ret_ref_val; } |
398 | |
399 | BOOST_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 | |
411 | struct model_ret_cref |
412 | { |
413 | const model_ret_cref& operator()() { return *this; } |
414 | }; |
415 | |
416 | BOOST_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 | |
428 | int f_ret_cref_val; |
429 | const int& f_ret_cref() { return f_ret_cref_val; } |
430 | |
431 | BOOST_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 | |
445 | int f_rv_value = 0; |
446 | void f_rv(int&& i) { f_rv_value += i; } |
447 | |
448 | BOOST_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 | |
461 | BOOST_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 | |
476 | BOOST_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 | |
489 | BOOST_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 | |
504 | struct model_ret_rref |
505 | { |
506 | model_ret_rref&& operator()() { return std::move(*this); } |
507 | }; |
508 | |
509 | BOOST_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 | |
521 | int f_ret_rv_val; |
522 | int&& f_ret_rv() { return std::move(f_ret_rv_val); } |
523 | |
524 | BOOST_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 | |