optional_test_value_access.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Copyright (C) 2014 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/lightweight_test.hpp"
  17. using boost::optional;
  18. struct IntWrapper
  19. {
  20. int _i;
  21. IntWrapper(int i) : _i(i) {}
  22. bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
  23. };
  24. template <typename T>
  25. void test_function_value_or_for()
  26. {
  27. optional<T> oM0;
  28. const optional<T> oC0;
  29. optional<T> oM1(1);
  30. const optional<T> oC2(2);
  31. BOOST_TEST(oM0.value_or(5) == 5);
  32. BOOST_TEST(oC0.value_or(5) == 5);
  33. BOOST_TEST(oM1.value_or(5) == 1);
  34. BOOST_TEST(oC2.value_or(5) == 2);
  35. }
  36. template <typename T>
  37. void test_function_value_for()
  38. {
  39. optional<T> o0;
  40. optional<T> o1(1);
  41. const optional<T> oC(2);
  42. try
  43. {
  44. T& v = o1.value();
  45. BOOST_TEST(v == 1);
  46. }
  47. catch(...)
  48. {
  49. BOOST_TEST(false);
  50. }
  51. try
  52. {
  53. T const& v = oC.value();
  54. BOOST_TEST(v == 2);
  55. }
  56. catch(...)
  57. {
  58. BOOST_TEST(false);
  59. }
  60. BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access);
  61. }
  62. void test_function_value()
  63. {
  64. test_function_value_for<int>();
  65. test_function_value_for<double>();
  66. test_function_value_for<IntWrapper>();
  67. }
  68. struct FatToIntConverter
  69. {
  70. static int conversions;
  71. int _val;
  72. FatToIntConverter(int val) : _val(val) {}
  73. operator int() const { conversions += 1; return _val; }
  74. };
  75. int FatToIntConverter::conversions = 0;
  76. void test_function_value_or()
  77. {
  78. test_function_value_or_for<int>();
  79. test_function_value_or_for<double>();
  80. test_function_value_or_for<IntWrapper>();
  81. optional<int> oi(1);
  82. BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1);
  83. BOOST_TEST(FatToIntConverter::conversions == 0);
  84. oi = boost::none;
  85. BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2);
  86. BOOST_TEST(FatToIntConverter::conversions == 1);
  87. }
  88. struct FunM
  89. {
  90. int operator()() { return 5; }
  91. };
  92. struct FunC
  93. {
  94. int operator()() const { return 6; }
  95. };
  96. int funP ()
  97. {
  98. return 7;
  99. }
  100. int throw_()
  101. {
  102. throw int();
  103. }
  104. void test_function_value_or_eval()
  105. {
  106. optional<int> o1 = 1;
  107. optional<int> oN;
  108. FunM funM;
  109. FunC funC;
  110. BOOST_TEST_EQ(o1.value_or_eval(funM), 1);
  111. BOOST_TEST_EQ(oN.value_or_eval(funM), 5);
  112. BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1);
  113. BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5);
  114. BOOST_TEST_EQ(o1.value_or_eval(funC), 1);
  115. BOOST_TEST_EQ(oN.value_or_eval(funC), 6);
  116. BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1);
  117. BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6);
  118. BOOST_TEST_EQ(o1.value_or_eval(funP), 1);
  119. BOOST_TEST_EQ(oN.value_or_eval(funP), 7);
  120. #ifndef BOOST_NO_CXX11_LAMBDAS
  121. BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1);
  122. BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8);
  123. #endif
  124. try
  125. {
  126. BOOST_TEST_EQ(o1.value_or_eval(throw_), 1);
  127. }
  128. catch(...)
  129. {
  130. BOOST_TEST(false);
  131. }
  132. BOOST_TEST_THROWS(oN.value_or_eval(throw_), int);
  133. }
  134. const optional<std::string> makeConstOptVal()
  135. {
  136. return std::string("something");
  137. }
  138. void test_const_move()
  139. {
  140. std::string s5 = *makeConstOptVal();
  141. std::string s6 = makeConstOptVal().value();
  142. boost::ignore_unused(s5);
  143. boost::ignore_unused(s6);
  144. }
  145. #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
  146. struct MoveOnly
  147. {
  148. explicit MoveOnly(int){}
  149. MoveOnly(MoveOnly &&){}
  150. void operator=(MoveOnly &&);
  151. private:
  152. MoveOnly(MoveOnly const&);
  153. void operator=(MoveOnly const&);
  154. };
  155. optional<MoveOnly> makeMoveOnly()
  156. {
  157. return MoveOnly(1);
  158. }
  159. MoveOnly moveOnlyDefault()
  160. {
  161. return MoveOnly(1);
  162. }
  163. // compile-time test
  164. void test_move_only_getters()
  165. {
  166. MoveOnly m1 = *makeMoveOnly();
  167. MoveOnly m2 = makeMoveOnly().value();
  168. MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1));
  169. MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault);
  170. boost::ignore_unused(m1);
  171. boost::ignore_unused(m2);
  172. boost::ignore_unused(m3);
  173. boost::ignore_unused(m4);
  174. }
  175. #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
  176. int main()
  177. {
  178. test_function_value();
  179. test_function_value_or();
  180. test_function_value_or_eval();
  181. test_const_move();
  182. return boost::report_errors();
  183. }