function_n_test.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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 <cassert>
  11. #include <string>
  12. #define BOOST_CHECK BOOST_TEST
  13. using namespace boost;
  14. using std::string;
  15. using std::negate;
  16. int global_int;
  17. struct write_five_obj { void operator()() const { global_int = 5; } };
  18. struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
  19. static void write_five() { global_int = 5; }
  20. static void write_three() { global_int = 3; }
  21. struct generate_five_obj { int operator()() const { return 5; } };
  22. struct generate_three_obj { int operator()() const { return 3; } };
  23. static int generate_five() { return 5; }
  24. static int generate_three() { return 3; }
  25. static string identity_str(const string& s) { return s; }
  26. static string string_cat(const string& s1, const string& s2) { return s1+s2; }
  27. static int sum_ints(int x, int y) { return x+y; }
  28. struct write_const_1_nonconst_2
  29. {
  30. void operator()() { global_int = 2; }
  31. void operator()() const { global_int = 1; }
  32. };
  33. struct add_to_obj
  34. {
  35. add_to_obj(int v) : value(v) {}
  36. int operator()(int x) const { return value + x; }
  37. int value;
  38. };
  39. static void
  40. test_zero_args()
  41. {
  42. typedef function0<void> func_void_type;
  43. write_five_obj five = write_five_obj(); // Initialization for Borland C++ 5.5
  44. write_three_obj three = write_three_obj(); // Ditto
  45. // Default construction
  46. func_void_type v1;
  47. BOOST_CHECK(v1.empty());
  48. // Assignment to an empty function
  49. v1 = five;
  50. BOOST_CHECK(!v1.empty());
  51. // Invocation of a function
  52. global_int = 0;
  53. v1();
  54. BOOST_CHECK(global_int == 5);
  55. // clear() method
  56. v1.clear();
  57. BOOST_CHECK(!v1);
  58. // Assignment to an empty function
  59. v1 = three;
  60. BOOST_CHECK(!v1.empty());
  61. // Invocation and self-assignment
  62. global_int = 0;
  63. v1 = v1;
  64. v1();
  65. BOOST_CHECK(global_int == 3);
  66. // Assignment to a non-empty function
  67. v1 = five;
  68. // Invocation and self-assignment
  69. global_int = 0;
  70. v1 = (v1);
  71. v1();
  72. BOOST_CHECK(global_int == 5);
  73. // clear
  74. v1 = 0;
  75. BOOST_CHECK(v1.empty());
  76. // Assignment to an empty function from a free function
  77. v1 = &write_five;
  78. BOOST_CHECK(!v1.empty());
  79. // Invocation
  80. global_int = 0;
  81. v1();
  82. BOOST_CHECK(global_int == 5);
  83. // Assignment to a non-empty function from a free function
  84. v1 = &write_three;
  85. BOOST_CHECK(!v1.empty());
  86. // Invocation
  87. global_int = 0;
  88. v1();
  89. BOOST_CHECK(global_int == 3);
  90. // Assignment
  91. v1 = five;
  92. BOOST_CHECK(!v1.empty());
  93. // Invocation
  94. global_int = 0;
  95. v1();
  96. BOOST_CHECK(global_int == 5);
  97. // Assignment to a non-empty function from a free function
  98. v1 = write_three;
  99. BOOST_CHECK(!v1.empty());
  100. // Invocation
  101. global_int = 0;
  102. v1();
  103. BOOST_CHECK(global_int == 3);
  104. // Construction from another function (that is empty)
  105. v1.clear();
  106. func_void_type v2(v1);
  107. BOOST_CHECK(!v2? true : false);
  108. // Assignment to an empty function
  109. v2 = three;
  110. BOOST_CHECK(!v2.empty());
  111. // Invocation
  112. global_int = 0;
  113. v2();
  114. BOOST_CHECK(global_int == 3);
  115. // Assignment to a non-empty function
  116. v2 = (five);
  117. // Invocation
  118. global_int = 0;
  119. v2();
  120. BOOST_CHECK(global_int == 5);
  121. v2.clear();
  122. BOOST_CHECK(v2.empty());
  123. // Assignment to an empty function from a free function
  124. v2 = (&write_five);
  125. BOOST_CHECK(v2? true : false);
  126. // Invocation
  127. global_int = 0;
  128. v2();
  129. BOOST_CHECK(global_int == 5);
  130. // Assignment to a non-empty function from a free function
  131. v2 = &write_three;
  132. BOOST_CHECK(!v2.empty());
  133. // Invocation
  134. global_int = 0;
  135. v2();
  136. BOOST_CHECK(global_int == 3);
  137. // Swapping
  138. v1 = five;
  139. swap(v1, v2);
  140. v2();
  141. BOOST_CHECK(global_int == 5);
  142. v1();
  143. BOOST_CHECK(global_int == 3);
  144. swap(v1, v2);
  145. v1.clear();
  146. // Assignment
  147. v2 = five;
  148. BOOST_CHECK(!v2.empty());
  149. // Invocation
  150. global_int = 0;
  151. v2();
  152. BOOST_CHECK(global_int == 5);
  153. // Assignment to a non-empty function from a free function
  154. v2 = &write_three;
  155. BOOST_CHECK(!v2.empty());
  156. // Invocation
  157. global_int = 0;
  158. v2();
  159. BOOST_CHECK(global_int == 3);
  160. // Assignment to a function from an empty function
  161. v2 = v1;
  162. BOOST_CHECK(v2.empty());
  163. // Assignment to a function from a function with a functor
  164. v1 = three;
  165. v2 = v1;
  166. BOOST_CHECK(!v1.empty());
  167. BOOST_CHECK(!v2.empty());
  168. // Invocation
  169. global_int = 0;
  170. v1();
  171. BOOST_CHECK(global_int == 3);
  172. global_int = 0;
  173. v2();
  174. BOOST_CHECK(global_int == 3);
  175. // Assign to a function from a function with a function
  176. v2 = &write_five;
  177. v1 = v2;
  178. BOOST_CHECK(!v1.empty());
  179. BOOST_CHECK(!v2.empty());
  180. global_int = 0;
  181. v1();
  182. BOOST_CHECK(global_int == 5);
  183. global_int = 0;
  184. v2();
  185. BOOST_CHECK(global_int == 5);
  186. // Construct a function given another function containing a function
  187. func_void_type v3(v1);
  188. // Invocation of a function
  189. global_int = 0;
  190. v3();
  191. BOOST_CHECK(global_int == 5);
  192. // clear() method
  193. v3.clear();
  194. BOOST_CHECK(!v3? true : false);
  195. // Assignment to an empty function
  196. v3 = three;
  197. BOOST_CHECK(!v3.empty());
  198. // Invocation
  199. global_int = 0;
  200. v3();
  201. BOOST_CHECK(global_int == 3);
  202. // Assignment to a non-empty function
  203. v3 = five;
  204. // Invocation
  205. global_int = 0;
  206. v3();
  207. BOOST_CHECK(global_int == 5);
  208. // clear()
  209. v3.clear();
  210. BOOST_CHECK(v3.empty());
  211. // Assignment to an empty function from a free function
  212. v3 = &write_five;
  213. BOOST_CHECK(!v3.empty());
  214. // Invocation
  215. global_int = 0;
  216. v3();
  217. BOOST_CHECK(global_int == 5);
  218. // Assignment to a non-empty function from a free function
  219. v3 = &write_three;
  220. BOOST_CHECK(!v3.empty());
  221. // Invocation
  222. global_int = 0;
  223. v3();
  224. BOOST_CHECK(global_int == 3);
  225. // Assignment
  226. v3 = five;
  227. BOOST_CHECK(!v3.empty());
  228. // Invocation
  229. global_int = 0;
  230. v3();
  231. BOOST_CHECK(global_int == 5);
  232. // Construction of a function from a function containing a functor
  233. func_void_type v4(v3);
  234. // Invocation of a function
  235. global_int = 0;
  236. v4();
  237. BOOST_CHECK(global_int == 5);
  238. // clear() method
  239. v4.clear();
  240. BOOST_CHECK(v4.empty());
  241. // Assignment to an empty function
  242. v4 = three;
  243. BOOST_CHECK(!v4.empty());
  244. // Invocation
  245. global_int = 0;
  246. v4();
  247. BOOST_CHECK(global_int == 3);
  248. // Assignment to a non-empty function
  249. v4 = five;
  250. // Invocation
  251. global_int = 0;
  252. v4();
  253. BOOST_CHECK(global_int == 5);
  254. // clear()
  255. v4.clear();
  256. BOOST_CHECK(v4.empty());
  257. // Assignment to an empty function from a free function
  258. v4 = &write_five;
  259. BOOST_CHECK(!v4.empty());
  260. // Invocation
  261. global_int = 0;
  262. v4();
  263. BOOST_CHECK(global_int == 5);
  264. // Assignment to a non-empty function from a free function
  265. v4 = &write_three;
  266. BOOST_CHECK(!v4.empty());
  267. // Invocation
  268. global_int = 0;
  269. v4();
  270. BOOST_CHECK(global_int == 3);
  271. // Assignment
  272. v4 = five;
  273. BOOST_CHECK(!v4.empty());
  274. // Invocation
  275. global_int = 0;
  276. v4();
  277. BOOST_CHECK(global_int == 5);
  278. // Construction of a function from a functor
  279. func_void_type v5(five);
  280. // Invocation of a function
  281. global_int = 0;
  282. v5();
  283. BOOST_CHECK(global_int == 5);
  284. // clear() method
  285. v5.clear();
  286. BOOST_CHECK(v5.empty());
  287. // Assignment to an empty function
  288. v5 = three;
  289. BOOST_CHECK(!v5.empty());
  290. // Invocation
  291. global_int = 0;
  292. v5();
  293. BOOST_CHECK(global_int == 3);
  294. // Assignment to a non-empty function
  295. v5 = five;
  296. // Invocation
  297. global_int = 0;
  298. v5();
  299. BOOST_CHECK(global_int == 5);
  300. // clear()
  301. v5.clear();
  302. BOOST_CHECK(v5.empty());
  303. // Assignment to an empty function from a free function
  304. v5 = &write_five;
  305. BOOST_CHECK(!v5.empty());
  306. // Invocation
  307. global_int = 0;
  308. v5();
  309. BOOST_CHECK(global_int == 5);
  310. // Assignment to a non-empty function from a free function
  311. v5 = &write_three;
  312. BOOST_CHECK(!v5.empty());
  313. // Invocation
  314. global_int = 0;
  315. v5();
  316. BOOST_CHECK(global_int == 3);
  317. // Assignment
  318. v5 = five;
  319. BOOST_CHECK(!v5.empty());
  320. // Invocation
  321. global_int = 0;
  322. v5();
  323. BOOST_CHECK(global_int == 5);
  324. // Construction of a function from a function
  325. func_void_type v6(&write_five);
  326. // Invocation of a function
  327. global_int = 0;
  328. v6();
  329. BOOST_CHECK(global_int == 5);
  330. // clear() method
  331. v6.clear();
  332. BOOST_CHECK(v6.empty());
  333. // Assignment to an empty function
  334. v6 = three;
  335. BOOST_CHECK(!v6.empty());
  336. // Invocation
  337. global_int = 0;
  338. v6();
  339. BOOST_CHECK(global_int == 3);
  340. // Assignment to a non-empty function
  341. v6 = five;
  342. // Invocation
  343. global_int = 0;
  344. v6();
  345. BOOST_CHECK(global_int == 5);
  346. // clear()
  347. v6.clear();
  348. BOOST_CHECK(v6.empty());
  349. // Assignment to an empty function from a free function
  350. v6 = &write_five;
  351. BOOST_CHECK(!v6.empty());
  352. // Invocation
  353. global_int = 0;
  354. v6();
  355. BOOST_CHECK(global_int == 5);
  356. // Assignment to a non-empty function from a free function
  357. v6 = &write_three;
  358. BOOST_CHECK(!v6.empty());
  359. // Invocation
  360. global_int = 0;
  361. v6();
  362. BOOST_CHECK(global_int == 3);
  363. // Assignment
  364. v6 = five;
  365. BOOST_CHECK(!v6.empty());
  366. // Invocation
  367. global_int = 0;
  368. v6();
  369. BOOST_CHECK(global_int == 5);
  370. // Const vs. non-const
  371. // Initialization for Borland C++ 5.5
  372. write_const_1_nonconst_2 one_or_two = write_const_1_nonconst_2();
  373. const function0<void> v7(one_or_two);
  374. function0<void> v8(one_or_two);
  375. global_int = 0;
  376. v7();
  377. BOOST_CHECK(global_int == 2);
  378. global_int = 0;
  379. v8();
  380. BOOST_CHECK(global_int == 2);
  381. // Test construction from 0 and comparison to 0
  382. func_void_type v9(0);
  383. BOOST_CHECK(v9 == 0);
  384. # if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG)
  385. BOOST_CHECK(0 == v9);
  386. #else
  387. BOOST_CHECK(v9.empty());
  388. #endif
  389. // Test return values
  390. typedef function0<int> func_int_type;
  391. // Initialization for Borland C++ 5.5
  392. generate_five_obj gen_five = generate_five_obj();
  393. generate_three_obj gen_three = generate_three_obj();
  394. func_int_type i0(gen_five);
  395. BOOST_CHECK(i0() == 5);
  396. i0 = gen_three;
  397. BOOST_CHECK(i0() == 3);
  398. i0 = &generate_five;
  399. BOOST_CHECK(i0() == 5);
  400. i0 = &generate_three;
  401. BOOST_CHECK(i0() == 3);
  402. BOOST_CHECK(i0? true : false);
  403. i0.clear();
  404. BOOST_CHECK(!i0? true : false);
  405. // Test return values with compatible types
  406. typedef function0<long> func_long_type;
  407. func_long_type i1(gen_five);
  408. BOOST_CHECK(i1() == 5);
  409. i1 = gen_three;
  410. BOOST_CHECK(i1() == 3);
  411. i1 = &generate_five;
  412. BOOST_CHECK(i1() == 5);
  413. i1 = &generate_three;
  414. BOOST_CHECK(i1() == 3);
  415. BOOST_CHECK(i1? true : false);
  416. i1.clear();
  417. BOOST_CHECK(!i1? true : false);
  418. }
  419. static void
  420. test_one_arg()
  421. {
  422. negate<int> neg = negate<int>(); // Initialization for Borland C++ 5.5
  423. function1<int, int> f1(neg);
  424. BOOST_CHECK(f1(5) == -5);
  425. function1<string, string> id(&identity_str);
  426. BOOST_CHECK(id("str") == "str");
  427. function1<std::string, const char*> id2(&identity_str);
  428. BOOST_CHECK(id2("foo") == "foo");
  429. add_to_obj add_to(5);
  430. function1<int, int> f2(add_to);
  431. BOOST_CHECK(f2(3) == 8);
  432. const function1<int, int> cf2(add_to);
  433. BOOST_CHECK(cf2(3) == 8);
  434. }
  435. static void
  436. test_two_args()
  437. {
  438. function2<string, const string&, const string&> cat(&string_cat);
  439. BOOST_CHECK(cat("str", "ing") == "string");
  440. function2<int, short, short> sum(&sum_ints);
  441. BOOST_CHECK(sum(2, 3) == 5);
  442. }
  443. static void
  444. test_emptiness()
  445. {
  446. function0<float> f1;
  447. BOOST_CHECK(f1.empty());
  448. function0<float> f2;
  449. f2 = f1;
  450. BOOST_CHECK(f2.empty());
  451. function0<double> f3;
  452. f3 = f2;
  453. BOOST_CHECK(f3.empty());
  454. }
  455. struct X {
  456. X(int v) : value(v) {}
  457. int twice() const { return 2*value; }
  458. int plus(int v) { return value + v; }
  459. int value;
  460. };
  461. static void
  462. test_member_functions()
  463. {
  464. boost::function1<int, X*> f1(&X::twice);
  465. X one(1);
  466. X five(5);
  467. BOOST_CHECK(f1(&one) == 2);
  468. BOOST_CHECK(f1(&five) == 10);
  469. boost::function1<int, X*> f1_2;
  470. f1_2 = &X::twice;
  471. BOOST_CHECK(f1_2(&one) == 2);
  472. BOOST_CHECK(f1_2(&five) == 10);
  473. boost::function2<int, X&, int> f2(&X::plus);
  474. BOOST_CHECK(f2(one, 3) == 4);
  475. BOOST_CHECK(f2(five, 4) == 9);
  476. }
  477. struct add_with_throw_on_copy {
  478. int operator()(int x, int y) const { return x+y; }
  479. add_with_throw_on_copy() {}
  480. add_with_throw_on_copy(const add_with_throw_on_copy&)
  481. {
  482. throw std::runtime_error("But this CAN'T throw");
  483. }
  484. add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
  485. {
  486. throw std::runtime_error("But this CAN'T throw");
  487. }
  488. };
  489. static void
  490. test_ref()
  491. {
  492. add_with_throw_on_copy atc;
  493. try {
  494. boost::function2<int, int, int> f(ref(atc));
  495. BOOST_CHECK(f(1, 3) == 4);
  496. }
  497. catch(std::runtime_error const&) {
  498. BOOST_ERROR("Nonthrowing constructor threw an exception");
  499. }
  500. }
  501. static unsigned construction_count = 0;
  502. static unsigned destruction_count = 0;
  503. struct MySmallFunctor {
  504. MySmallFunctor() { ++construction_count; }
  505. MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
  506. ~MySmallFunctor() { ++destruction_count; }
  507. int operator()() { return 0; }
  508. };
  509. struct MyLargeFunctor {
  510. MyLargeFunctor() { ++construction_count; }
  511. MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
  512. ~MyLargeFunctor() { ++destruction_count; }
  513. int operator()() { return 0; }
  514. float data[128];
  515. };
  516. void test_construct_destroy_count()
  517. {
  518. {
  519. boost::function0<int> f;
  520. boost::function0<int> g;
  521. f = MySmallFunctor();
  522. g = MySmallFunctor();
  523. f.swap(g);
  524. }
  525. // MySmallFunctor objects should be constructed as many times as
  526. // they are destroyed.
  527. BOOST_CHECK(construction_count == destruction_count);
  528. construction_count = 0;
  529. destruction_count = 0;
  530. {
  531. boost::function0<int> f;
  532. boost::function0<int> g;
  533. f = MyLargeFunctor();
  534. g = MyLargeFunctor();
  535. f.swap(g);
  536. }
  537. // MyLargeFunctor objects should be constructed as many times as
  538. // they are destroyed.
  539. BOOST_CHECK(construction_count == destruction_count);
  540. }
  541. int main()
  542. {
  543. test_zero_args();
  544. test_one_arg();
  545. test_two_args();
  546. test_emptiness();
  547. test_member_functions();
  548. test_ref();
  549. test_construct_destroy_count();
  550. return boost::report_errors();
  551. }