test_callable.cpp 13 KB

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