optional_test_flat_map.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright (C) 2018 Andrzej Krzemienski.
  2. //
  3. // Use, modification, and distribution is subject to the Boost Software
  4. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/lib/optional for documentation.
  8. //
  9. // You are welcome to contact the author at:
  10. // akrzemi1@gmail.com
  11. #include "boost/optional/optional.hpp"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #include "boost/core/ignore_unused.hpp"
  16. #include "boost/core/is_same.hpp"
  17. #include "boost/core/lightweight_test.hpp"
  18. #include "boost/core/lightweight_test_trait.hpp"
  19. using boost::optional;
  20. using boost::make_optional;
  21. using boost::core::is_same;
  22. template <typename Expected, typename Deduced>
  23. void verify_type(Deduced)
  24. {
  25. BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
  26. }
  27. struct Int
  28. {
  29. int i;
  30. explicit Int(int i_) : i(i_) {}
  31. };
  32. struct convert_t
  33. {
  34. typedef optional<Int> result_type;
  35. optional<Int> operator()(int i) { if (i != 0) return Int(i); else return boost::none; }
  36. };
  37. void test_flat_map_on_mutable_optional_with_function_object()
  38. {
  39. {
  40. optional<int> oi (1);
  41. verify_type< optional<Int> >(oi.flat_map(convert_t()));
  42. optional<Int> oI = oi.flat_map(convert_t());
  43. BOOST_TEST(bool(oI));
  44. BOOST_TEST_EQ(1, oI->i);
  45. }
  46. {
  47. optional<int> oi (0);
  48. optional<Int> oI = oi.flat_map(convert_t());
  49. BOOST_TEST(!oI);
  50. }
  51. {
  52. optional<int> oi;
  53. optional<Int> oI = oi.flat_map(convert_t());
  54. BOOST_TEST(!oI);
  55. }
  56. }
  57. void test_flat_map_on_const_optional_with_function_object()
  58. {
  59. {
  60. const optional<int> oi (1);
  61. verify_type< optional<Int> >(oi.flat_map(convert_t()));
  62. optional<Int> oI = oi.flat_map(convert_t());
  63. BOOST_TEST(bool(oI));
  64. BOOST_TEST_EQ(1, oI->i);
  65. }
  66. {
  67. const optional<int> oi (0);
  68. optional<Int> oI = oi.flat_map(convert_t());
  69. BOOST_TEST(!oI);
  70. }
  71. {
  72. const optional<int> oi;
  73. optional<Int> oI = oi.flat_map(convert_t());
  74. BOOST_TEST(!oI);
  75. }
  76. }
  77. void test_flat_map_with_lambda()
  78. {
  79. #if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276
  80. {
  81. optional<int> oi (1);
  82. verify_type< optional<Int> >(oi.flat_map([](int i){ return optional<Int>(i == 0, Int(i)); }));
  83. optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
  84. BOOST_TEST(bool(oI));
  85. BOOST_TEST_EQ(1, oI->i);
  86. }
  87. {
  88. optional<int> oi (0);
  89. optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
  90. BOOST_TEST(!oI);
  91. }
  92. {
  93. optional<int> oi;
  94. optional<Int> oI = oi.flat_map([](int i){ return optional<Int>(i != 0, Int(i)); });
  95. BOOST_TEST(!oI);
  96. }
  97. #endif // lambdas
  98. }
  99. struct get_opt_ref
  100. {
  101. typedef optional<int&> result_type;
  102. optional<int&> operator()(int& i) { return i != 0 ? optional<int&>(i) : optional<int&>(); }
  103. };
  104. void test_flat_map_obj_to_ref()
  105. {
  106. {
  107. optional<int> oi (2);
  108. verify_type< optional<int&> >(oi.flat_map(get_opt_ref()));
  109. optional<int&> ori = oi.flat_map(get_opt_ref());
  110. BOOST_TEST(bool(ori));
  111. BOOST_TEST_EQ(2, *ori);
  112. *ori = 3;
  113. BOOST_TEST(bool(oi));
  114. BOOST_TEST_EQ(3, *oi);
  115. BOOST_TEST_EQ(3, *ori);
  116. }
  117. {
  118. optional<int> oi (0);
  119. optional<int&> ori = oi.flat_map(get_opt_ref());
  120. BOOST_TEST(!ori);
  121. }
  122. {
  123. optional<int> oi;
  124. optional<int&> ori = oi.flat_map(get_opt_ref());
  125. BOOST_TEST(!ori);
  126. }
  127. }
  128. optional<int&> get_opt_int_ref(Int& i)
  129. {
  130. return i.i ? optional<int&>(i.i) : optional<int&>();
  131. }
  132. void test_flat_map_ref_to_ref()
  133. {
  134. {
  135. Int I (5);
  136. optional<Int&> orI (I);
  137. verify_type< optional<int&> >(orI.flat_map(get_opt_int_ref));
  138. optional<int&> ori = orI.flat_map(get_opt_int_ref);
  139. BOOST_TEST(bool(ori));
  140. BOOST_TEST_EQ(5, *ori);
  141. *ori = 6;
  142. BOOST_TEST_EQ(6, *ori);
  143. BOOST_TEST_EQ(6, I.i);
  144. }
  145. {
  146. Int I (0);
  147. optional<Int&> orI (I);
  148. optional<int&> ori = orI.flat_map(get_opt_int_ref);
  149. BOOST_TEST(!ori);
  150. }
  151. {
  152. optional<Int&> orI;
  153. optional<int&> ori = orI.flat_map(get_opt_int_ref);
  154. BOOST_TEST(!ori);
  155. }
  156. }
  157. optional< optional<Int> > make_opt_int(int i)
  158. {
  159. if (i == 0)
  160. return boost::none;
  161. else if (i == 1)
  162. return boost::make_optional(optional<Int>());
  163. else
  164. return boost::make_optional(boost::make_optional(Int(i)));
  165. }
  166. void test_flat_map_opt_opt()
  167. {
  168. {
  169. optional<int> oi (9);
  170. verify_type<optional<optional<Int> > >(oi.flat_map(make_opt_int));
  171. optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
  172. BOOST_TEST(bool(ooI));
  173. BOOST_TEST(bool(*ooI));
  174. BOOST_TEST_EQ(9, (**ooI).i);
  175. }
  176. {
  177. optional<int> oi (1);
  178. optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
  179. BOOST_TEST(bool(ooI));
  180. BOOST_TEST(!*ooI);
  181. }
  182. {
  183. optional<int> oi (0);
  184. optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
  185. BOOST_TEST(!ooI);
  186. }
  187. {
  188. optional<int> oi;
  189. optional<optional<Int> > ooI = oi.flat_map(make_opt_int);
  190. BOOST_TEST(!ooI);
  191. }
  192. }
  193. #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  194. struct MoveOnly
  195. {
  196. int value;
  197. explicit MoveOnly(int i) : value(i) {}
  198. MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
  199. MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
  200. private:
  201. MoveOnly(MoveOnly const&);
  202. void operator=(MoveOnly const&);
  203. };
  204. MoveOnly makeMoveOnly(int i)
  205. {
  206. return MoveOnly(i);
  207. }
  208. optional<MoveOnly> makeOptMoveOnly(int i)
  209. {
  210. return optional<MoveOnly>(MoveOnly(i));
  211. }
  212. optional<int> get_val(MoveOnly m)
  213. {
  214. return optional<int>(m.value != 0, m.value);
  215. }
  216. void test_flat_map_move_only()
  217. {
  218. {
  219. optional<MoveOnly> om (makeMoveOnly(1)), om2 (makeMoveOnly(2));
  220. verify_type<optional<int> >(boost::move(om).flat_map(get_val));
  221. optional<int> oi = boost::move(om2).flat_map(get_val);
  222. BOOST_TEST(bool(oi));
  223. BOOST_TEST_EQ(2, *oi);
  224. }
  225. {
  226. optional<int> oj = makeOptMoveOnly(4).flat_map(get_val);
  227. BOOST_TEST(bool(oj));
  228. BOOST_TEST_EQ(4, *oj);
  229. }
  230. {
  231. optional<int> oj = optional<MoveOnly>().flat_map(get_val);
  232. BOOST_TEST(!oj);
  233. }
  234. }
  235. #endif // no rvalue refs
  236. int main()
  237. {
  238. test_flat_map_on_mutable_optional_with_function_object();
  239. test_flat_map_on_const_optional_with_function_object();
  240. test_flat_map_with_lambda();
  241. test_flat_map_obj_to_ref();
  242. test_flat_map_ref_to_ref();
  243. test_flat_map_opt_opt();
  244. #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  245. test_flat_map_move_only();
  246. #endif
  247. return boost::report_errors();
  248. }