function_test.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. // Boost.Function library
  2. // Copyright Douglas Gregor 2001-2003. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // For more information, see http://www.boost.org
  7. #include <boost/function.hpp>
  8. #include <boost/core/lightweight_test.hpp>
  9. #include <functional>
  10. #include <string>
  11. #include <utility>
  12. #define BOOST_CHECK BOOST_TEST
  13. using boost::function;
  14. using std::string;
  15. int global_int;
  16. struct write_five_obj { void operator()() const { global_int = 5; } };
  17. struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
  18. static void write_five() { global_int = 5; }
  19. static void write_three() { global_int = 3; }
  20. struct generate_five_obj { int operator()() const { return 5; } };
  21. struct generate_three_obj { int operator()() const { return 3; } };
  22. static int generate_five() { return 5; }
  23. static int generate_three() { return 3; }
  24. static string identity_str(const string& s) { return s; }
  25. static string string_cat(const string& s1, const string& s2) { return s1+s2; }
  26. static int sum_ints(int x, int y) { return x+y; }
  27. struct write_const_1_nonconst_2
  28. {
  29. void operator()() { global_int = 2; }
  30. void operator()() const { global_int = 1; }
  31. };
  32. struct add_to_obj
  33. {
  34. add_to_obj(int v) : value(v) {}
  35. int operator()(int x) const { return value + x; }
  36. int value;
  37. };
  38. static void
  39. test_zero_args()
  40. {
  41. typedef function<void ()> func_void_type;
  42. write_five_obj five;
  43. write_three_obj three;
  44. // Default construction
  45. func_void_type v1;
  46. BOOST_CHECK(v1.empty());
  47. // Assignment to an empty function
  48. v1 = five;
  49. BOOST_CHECK(v1 != 0);
  50. // Invocation of a function
  51. global_int = 0;
  52. v1();
  53. BOOST_CHECK(global_int == 5);
  54. // clear() method
  55. v1.clear();
  56. BOOST_CHECK(v1 == 0);
  57. // Assignment to an empty function
  58. v1 = three;
  59. BOOST_CHECK(!v1.empty());
  60. // Invocation and self-assignment
  61. global_int = 0;
  62. v1 = v1;
  63. v1();
  64. BOOST_CHECK(global_int == 3);
  65. // Assignment to a non-empty function
  66. v1 = five;
  67. // Invocation and self-assignment
  68. global_int = 0;
  69. v1 = (v1);
  70. v1();
  71. BOOST_CHECK(global_int == 5);
  72. // clear
  73. v1 = 0;
  74. BOOST_CHECK(0 == v1);
  75. // Assignment to an empty function from a free function
  76. v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
  77. BOOST_CHECK(0 != v1);
  78. // Invocation
  79. global_int = 0;
  80. v1();
  81. BOOST_CHECK(global_int == 5);
  82. // Assignment to a non-empty function from a free function
  83. v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
  84. BOOST_CHECK(!v1.empty());
  85. // Invocation
  86. global_int = 0;
  87. v1();
  88. BOOST_CHECK(global_int == 3);
  89. // Assignment
  90. v1 = five;
  91. BOOST_CHECK(!v1.empty());
  92. // Invocation
  93. global_int = 0;
  94. v1();
  95. BOOST_CHECK(global_int == 5);
  96. // Assignment to a non-empty function from a free function
  97. v1 = &write_three;
  98. BOOST_CHECK(!v1.empty());
  99. // Invocation
  100. global_int = 0;
  101. v1();
  102. BOOST_CHECK(global_int == 3);
  103. // Construction from another function (that is empty)
  104. v1.clear();
  105. func_void_type v2(v1);
  106. BOOST_CHECK(!v2? true : false);
  107. // Assignment to an empty function
  108. v2 = three;
  109. BOOST_CHECK(!v2.empty());
  110. // Invocation
  111. global_int = 0;
  112. v2();
  113. BOOST_CHECK(global_int == 3);
  114. // Assignment to a non-empty function
  115. v2 = (five);
  116. // Invocation
  117. global_int = 0;
  118. v2();
  119. BOOST_CHECK(global_int == 5);
  120. v2.clear();
  121. BOOST_CHECK(v2.empty());
  122. // Assignment to an empty function from a free function
  123. v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
  124. BOOST_CHECK(v2? true : false);
  125. // Invocation
  126. global_int = 0;
  127. v2();
  128. BOOST_CHECK(global_int == 5);
  129. // Assignment to a non-empty function from a free function
  130. v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
  131. BOOST_CHECK(!v2.empty());
  132. // Invocation
  133. global_int = 0;
  134. v2();
  135. BOOST_CHECK(global_int == 3);
  136. // Swapping
  137. v1 = five;
  138. swap(v1, v2);
  139. v2();
  140. BOOST_CHECK(global_int == 5);
  141. v1();
  142. BOOST_CHECK(global_int == 3);
  143. swap(v1, v2);
  144. v1.clear();
  145. // Assignment
  146. v2 = five;
  147. BOOST_CHECK(!v2.empty());
  148. // Invocation
  149. global_int = 0;
  150. v2();
  151. BOOST_CHECK(global_int == 5);
  152. // Assignment to a non-empty function from a free function
  153. v2 = &write_three;
  154. BOOST_CHECK(!v2.empty());
  155. // Invocation
  156. global_int = 0;
  157. v2();
  158. BOOST_CHECK(global_int == 3);
  159. // Assignment to a function from an empty function
  160. v2 = v1;
  161. BOOST_CHECK(v2.empty());
  162. // Assignment to a function from a function with a functor
  163. v1 = three;
  164. v2 = v1;
  165. BOOST_CHECK(!v1.empty());
  166. BOOST_CHECK(!v2.empty());
  167. // Invocation
  168. global_int = 0;
  169. v1();
  170. BOOST_CHECK(global_int == 3);
  171. global_int = 0;
  172. v2();
  173. BOOST_CHECK(global_int == 3);
  174. // Assign to a function from a function with a function
  175. v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
  176. v1 = v2;
  177. BOOST_CHECK(!v1.empty());
  178. BOOST_CHECK(!v2.empty());
  179. global_int = 0;
  180. v1();
  181. BOOST_CHECK(global_int == 5);
  182. global_int = 0;
  183. v2();
  184. BOOST_CHECK(global_int == 5);
  185. // Construct a function given another function containing a function
  186. func_void_type v3(v1);
  187. // Invocation of a function
  188. global_int = 0;
  189. v3();
  190. BOOST_CHECK(global_int == 5);
  191. // clear() method
  192. v3.clear();
  193. BOOST_CHECK(!v3? true : false);
  194. // Assignment to an empty function
  195. v3 = three;
  196. BOOST_CHECK(!v3.empty());
  197. // Invocation
  198. global_int = 0;
  199. v3();
  200. BOOST_CHECK(global_int == 3);
  201. // Assignment to a non-empty function
  202. v3 = five;
  203. // Invocation
  204. global_int = 0;
  205. v3();
  206. BOOST_CHECK(global_int == 5);
  207. // clear()
  208. v3.clear();
  209. BOOST_CHECK(v3.empty());
  210. // Assignment to an empty function from a free function
  211. v3 = &write_five;
  212. BOOST_CHECK(!v3.empty());
  213. // Invocation
  214. global_int = 0;
  215. v3();
  216. BOOST_CHECK(global_int == 5);
  217. // Assignment to a non-empty function from a free function
  218. v3 = &write_three;
  219. BOOST_CHECK(!v3.empty());
  220. // Invocation
  221. global_int = 0;
  222. v3();
  223. BOOST_CHECK(global_int == 3);
  224. // Assignment
  225. v3 = five;
  226. BOOST_CHECK(!v3.empty());
  227. // Invocation
  228. global_int = 0;
  229. v3();
  230. BOOST_CHECK(global_int == 5);
  231. // Construction of a function from a function containing a functor
  232. func_void_type v4(v3);
  233. // Invocation of a function
  234. global_int = 0;
  235. v4();
  236. BOOST_CHECK(global_int == 5);
  237. // clear() method
  238. v4.clear();
  239. BOOST_CHECK(v4.empty());
  240. // Assignment to an empty function
  241. v4 = three;
  242. BOOST_CHECK(!v4.empty());
  243. // Invocation
  244. global_int = 0;
  245. v4();
  246. BOOST_CHECK(global_int == 3);
  247. // Assignment to a non-empty function
  248. v4 = five;
  249. // Invocation
  250. global_int = 0;
  251. v4();
  252. BOOST_CHECK(global_int == 5);
  253. // clear()
  254. v4.clear();
  255. BOOST_CHECK(v4.empty());
  256. // Assignment to an empty function from a free function
  257. v4 = &write_five;
  258. BOOST_CHECK(!v4.empty());
  259. // Invocation
  260. global_int = 0;
  261. v4();
  262. BOOST_CHECK(global_int == 5);
  263. // Assignment to a non-empty function from a free function
  264. v4 = &write_three;
  265. BOOST_CHECK(!v4.empty());
  266. // Invocation
  267. global_int = 0;
  268. v4();
  269. BOOST_CHECK(global_int == 3);
  270. // Assignment
  271. v4 = five;
  272. BOOST_CHECK(!v4.empty());
  273. // Invocation
  274. global_int = 0;
  275. v4();
  276. BOOST_CHECK(global_int == 5);
  277. // Construction of a function from a functor
  278. func_void_type v5(five);
  279. // Invocation of a function
  280. global_int = 0;
  281. v5();
  282. BOOST_CHECK(global_int == 5);
  283. // clear() method
  284. v5.clear();
  285. BOOST_CHECK(v5.empty());
  286. // Assignment to an empty function
  287. v5 = three;
  288. BOOST_CHECK(!v5.empty());
  289. // Invocation
  290. global_int = 0;
  291. v5();
  292. BOOST_CHECK(global_int == 3);
  293. // Assignment to a non-empty function
  294. v5 = five;
  295. // Invocation
  296. global_int = 0;
  297. v5();
  298. BOOST_CHECK(global_int == 5);
  299. // clear()
  300. v5.clear();
  301. BOOST_CHECK(v5.empty());
  302. // Assignment to an empty function from a free function
  303. v5 = &write_five;
  304. BOOST_CHECK(!v5.empty());
  305. // Invocation
  306. global_int = 0;
  307. v5();
  308. BOOST_CHECK(global_int == 5);
  309. // Assignment to a non-empty function from a free function
  310. v5 = &write_three;
  311. BOOST_CHECK(!v5.empty());
  312. // Invocation
  313. global_int = 0;
  314. v5();
  315. BOOST_CHECK(global_int == 3);
  316. // Assignment
  317. v5 = five;
  318. BOOST_CHECK(!v5.empty());
  319. // Invocation
  320. global_int = 0;
  321. v5();
  322. BOOST_CHECK(global_int == 5);
  323. // Construction of a function from a function
  324. func_void_type v6(&write_five);
  325. // Invocation of a function
  326. global_int = 0;
  327. v6();
  328. BOOST_CHECK(global_int == 5);
  329. // clear() method
  330. v6.clear();
  331. BOOST_CHECK(v6.empty());
  332. // Assignment to an empty function
  333. v6 = three;
  334. BOOST_CHECK(!v6.empty());
  335. // Invocation
  336. global_int = 0;
  337. v6();
  338. BOOST_CHECK(global_int == 3);
  339. // Assignment to a non-empty function
  340. v6 = five;
  341. // Invocation
  342. global_int = 0;
  343. v6();
  344. BOOST_CHECK(global_int == 5);
  345. // clear()
  346. v6.clear();
  347. BOOST_CHECK(v6.empty());
  348. // Assignment to an empty function from a free function
  349. v6 = &write_five;
  350. BOOST_CHECK(!v6.empty());
  351. // Invocation
  352. global_int = 0;
  353. v6();
  354. BOOST_CHECK(global_int == 5);
  355. // Assignment to a non-empty function from a free function
  356. v6 = &write_three;
  357. BOOST_CHECK(!v6.empty());
  358. // Invocation
  359. global_int = 0;
  360. v6();
  361. BOOST_CHECK(global_int == 3);
  362. // Assignment
  363. v6 = five;
  364. BOOST_CHECK(!v6.empty());
  365. // Invocation
  366. global_int = 0;
  367. v6();
  368. BOOST_CHECK(global_int == 5);
  369. // Const vs. non-const
  370. write_const_1_nonconst_2 one_or_two;
  371. const function<void ()> v7(one_or_two);
  372. function<void ()> v8(one_or_two);
  373. global_int = 0;
  374. v7();
  375. BOOST_CHECK(global_int == 2);
  376. global_int = 0;
  377. v8();
  378. BOOST_CHECK(global_int == 2);
  379. // Test construction from 0 and comparison to 0
  380. func_void_type v9(0);
  381. BOOST_CHECK(v9 == 0);
  382. BOOST_CHECK(0 == v9);
  383. // Test return values
  384. typedef function<int ()> func_int_type;
  385. generate_five_obj gen_five;
  386. generate_three_obj gen_three;
  387. func_int_type i0(gen_five);
  388. BOOST_CHECK(i0() == 5);
  389. i0 = gen_three;
  390. BOOST_CHECK(i0() == 3);
  391. i0 = &generate_five;
  392. BOOST_CHECK(i0() == 5);
  393. i0 = &generate_three;
  394. BOOST_CHECK(i0() == 3);
  395. BOOST_CHECK(i0? true : false);
  396. i0.clear();
  397. BOOST_CHECK(!i0? true : false);
  398. // Test return values with compatible types
  399. typedef function<long ()> func_long_type;
  400. func_long_type i1(gen_five);
  401. BOOST_CHECK(i1() == 5);
  402. i1 = gen_three;
  403. BOOST_CHECK(i1() == 3);
  404. i1 = &generate_five;
  405. BOOST_CHECK(i1() == 5);
  406. i1 = &generate_three;
  407. BOOST_CHECK(i1() == 3);
  408. BOOST_CHECK(i1? true : false);
  409. i1.clear();
  410. BOOST_CHECK(!i1? true : false);
  411. }
  412. static void
  413. test_one_arg()
  414. {
  415. std::negate<int> neg;
  416. function<int (int)> f1(neg);
  417. BOOST_CHECK(f1(5) == -5);
  418. function<string (string)> id(&identity_str);
  419. BOOST_CHECK(id("str") == "str");
  420. function<string (const char*)> id2(&identity_str);
  421. BOOST_CHECK(id2("foo") == "foo");
  422. add_to_obj add_to(5);
  423. function<int (int)> f2(add_to);
  424. BOOST_CHECK(f2(3) == 8);
  425. const function<int (int)> cf2(add_to);
  426. BOOST_CHECK(cf2(3) == 8);
  427. }
  428. static void
  429. test_two_args()
  430. {
  431. function<string (const string&, const string&)> cat(&string_cat);
  432. BOOST_CHECK(cat("str", "ing") == "string");
  433. function<int (short, short)> sum(&sum_ints);
  434. BOOST_CHECK(sum(2, 3) == 5);
  435. }
  436. static void
  437. test_emptiness()
  438. {
  439. function<float ()> f1;
  440. BOOST_CHECK(f1.empty());
  441. function<float ()> f2;
  442. f2 = f1;
  443. BOOST_CHECK(f2.empty());
  444. function<double ()> f3;
  445. f3 = f2;
  446. BOOST_CHECK(f3.empty());
  447. }
  448. struct X {
  449. X(int v) : value(v) {}
  450. int twice() const { return 2*value; }
  451. int plus(int v) { return value + v; }
  452. int value;
  453. };
  454. static void
  455. test_member_functions()
  456. {
  457. boost::function<int (X*)> f1(&X::twice);
  458. X one(1);
  459. X five(5);
  460. BOOST_CHECK(f1(&one) == 2);
  461. BOOST_CHECK(f1(&five) == 10);
  462. boost::function<int (X*)> f1_2;
  463. f1_2 = &X::twice;
  464. BOOST_CHECK(f1_2(&one) == 2);
  465. BOOST_CHECK(f1_2(&five) == 10);
  466. boost::function<int (X&, int)> f2(&X::plus);
  467. BOOST_CHECK(f2(one, 3) == 4);
  468. BOOST_CHECK(f2(five, 4) == 9);
  469. }
  470. struct add_with_throw_on_copy {
  471. int operator()(int x, int y) const { return x+y; }
  472. add_with_throw_on_copy() {}
  473. add_with_throw_on_copy(const add_with_throw_on_copy&)
  474. {
  475. throw std::runtime_error("But this CAN'T throw");
  476. }
  477. add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
  478. {
  479. throw std::runtime_error("But this CAN'T throw");
  480. }
  481. };
  482. static void
  483. test_ref()
  484. {
  485. add_with_throw_on_copy atc;
  486. try {
  487. boost::function<int (int, int)> f(boost::ref(atc));
  488. BOOST_CHECK(f(1, 3) == 4);
  489. }
  490. catch(std::runtime_error const&) {
  491. BOOST_ERROR("Nonthrowing constructor threw an exception");
  492. }
  493. }
  494. #if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700
  495. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311
  496. #pragma message("Skipping test_empty_ref on g++ 7 -std=c++17")
  497. static void test_empty_ref()
  498. {
  499. }
  500. #else
  501. static void dummy() {}
  502. static void test_empty_ref()
  503. {
  504. boost::function<void()> f1;
  505. boost::function<void()> f2(boost::ref(f1));
  506. try {
  507. f2();
  508. BOOST_ERROR("Exception didn't throw for reference to empty function.");
  509. }
  510. catch(std::runtime_error const&) {}
  511. f1 = dummy;
  512. try {
  513. f2();
  514. }
  515. catch(std::runtime_error const&) {
  516. BOOST_ERROR("Error calling referenced function.");
  517. }
  518. }
  519. #endif
  520. static void test_exception()
  521. {
  522. boost::function<int (int, int)> f;
  523. try {
  524. f(5, 4);
  525. BOOST_CHECK(false);
  526. }
  527. catch(boost::bad_function_call const&) {
  528. // okay
  529. }
  530. }
  531. typedef boost::function< void * (void * reader) > reader_type;
  532. typedef std::pair<int, reader_type> mapped_type;
  533. static void test_implicit()
  534. {
  535. mapped_type m;
  536. m = mapped_type();
  537. }
  538. static void test_call_obj(boost::function<int (int, int)> f)
  539. {
  540. BOOST_CHECK(!f.empty());
  541. }
  542. static void test_call_cref(const boost::function<int (int, int)>& f)
  543. {
  544. BOOST_CHECK(!f.empty());
  545. }
  546. static void test_call()
  547. {
  548. test_call_obj(std::plus<int>());
  549. test_call_cref(std::plus<int>());
  550. }
  551. struct big_aggregating_structure {
  552. int disable_small_objects_optimizations[32];
  553. big_aggregating_structure()
  554. {
  555. ++ global_int;
  556. }
  557. big_aggregating_structure(const big_aggregating_structure&)
  558. {
  559. ++ global_int;
  560. }
  561. ~big_aggregating_structure()
  562. {
  563. -- global_int;
  564. }
  565. void operator()()
  566. {
  567. ++ global_int;
  568. }
  569. void operator()(int)
  570. {
  571. ++ global_int;
  572. }
  573. };
  574. template <class FunctionT>
  575. static void test_move_semantics()
  576. {
  577. typedef FunctionT f1_type;
  578. big_aggregating_structure obj;
  579. f1_type f1 = obj;
  580. global_int = 0;
  581. f1();
  582. BOOST_CHECK(!f1.empty());
  583. BOOST_CHECK(global_int == 1);
  584. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  585. // Testing rvalue constructors
  586. f1_type f2(static_cast<f1_type&&>(f1));
  587. BOOST_CHECK(f1.empty());
  588. BOOST_CHECK(!f2.empty());
  589. BOOST_CHECK(global_int == 1);
  590. f2();
  591. BOOST_CHECK(global_int == 2);
  592. f1_type f3(static_cast<f1_type&&>(f2));
  593. BOOST_CHECK(f1.empty());
  594. BOOST_CHECK(f2.empty());
  595. BOOST_CHECK(!f3.empty());
  596. BOOST_CHECK(global_int == 2);
  597. f3();
  598. BOOST_CHECK(global_int == 3);
  599. // Testing move assignment
  600. f1_type f4;
  601. BOOST_CHECK(f4.empty());
  602. f4 = static_cast<f1_type&&>(f3);
  603. BOOST_CHECK(f1.empty());
  604. BOOST_CHECK(f2.empty());
  605. BOOST_CHECK(f3.empty());
  606. BOOST_CHECK(!f4.empty());
  607. BOOST_CHECK(global_int == 3);
  608. f4();
  609. BOOST_CHECK(global_int == 4);
  610. // Testing self move assignment
  611. f4 = static_cast<f1_type&&>(f4);
  612. BOOST_CHECK(!f4.empty());
  613. BOOST_CHECK(global_int == 4);
  614. // Testing, that no memory leaked when assigning to nonempty function
  615. f4 = obj;
  616. BOOST_CHECK(!f4.empty());
  617. BOOST_CHECK(global_int == 4);
  618. f1_type f5 = obj;
  619. BOOST_CHECK(global_int == 5);
  620. f4 = static_cast<f1_type&&>(f5);
  621. BOOST_CHECK(global_int == 4);
  622. #endif
  623. }
  624. int main()
  625. {
  626. test_zero_args();
  627. test_one_arg();
  628. test_two_args();
  629. test_emptiness();
  630. test_member_functions();
  631. test_ref();
  632. test_empty_ref();
  633. test_exception();
  634. test_implicit();
  635. test_call();
  636. test_move_semantics<function<void()> >();
  637. test_move_semantics<boost::function0<void> >();
  638. return boost::report_errors();
  639. }