algorithms.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (c) 2009-2016 Vladimir Batov.
  2. // Use, modification and distribution are subject to the Boost Software License,
  3. // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
  4. #include <boost/convert.hpp>
  5. #include <boost/convert/stream.hpp>
  6. #include <boost/convert/lexical_cast.hpp>
  7. #include <boost/detail/lightweight_test.hpp>
  8. #include <boost/array.hpp>
  9. #include <boost/bind.hpp>
  10. #include <vector>
  11. using std::string;
  12. static
  13. void
  14. introduction()
  15. {
  16. //[algorithm_introduction
  17. /*`The following code demonstrates conversion of an array of integers from their textual ['hexadecimal]
  18. representation. It assigns -1 to those which fail to convert:
  19. */
  20. boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  21. std::vector<int> ints;
  22. boost::cnv::cstream cnv;
  23. // Configure converter to read hexadecimal, skip (leading) white spaces.
  24. cnv(std::hex)(std::skipws);
  25. std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
  26. boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
  27. BOOST_TEST(ints.size() == 3); // Number of values processed.
  28. BOOST_TEST(ints[0] == 5); // " 5"
  29. BOOST_TEST(ints[1] == 15); // "0XF"
  30. BOOST_TEST(ints[2] == -1); // "not an int"
  31. //]
  32. }
  33. static
  34. void
  35. example1()
  36. {
  37. //[algorithm_example1
  38. /*`The following code demonstrates a failed attempt (and one of the reasons ['Boost.Convert]
  39. has been developed) to convert a few `string`s to `int`s with `boost::lexical_cast`:
  40. */
  41. boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  42. std::vector<int> ints;
  43. try
  44. {
  45. std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
  46. boost::bind(boost::lexical_cast<int, string>, _1));
  47. BOOST_TEST(0 && "Never reached!");
  48. }
  49. catch (std::exception&)
  50. {
  51. BOOST_TEST(ints.size() == 0); // No strings converted.
  52. }
  53. //]
  54. }
  55. static
  56. void
  57. example2()
  58. {
  59. //[algorithm_example2
  60. /*`If the exception-throwing behavior is the desired behavior, then ['Boost.Convert] supports that.
  61. In addition, it also supports a non-throwing process-flow:
  62. */
  63. boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  64. std::vector<int> ints;
  65. std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
  66. boost::cnv::apply<int>(boost::cnv::lexical_cast()).value_or(-1));
  67. BOOST_TEST(ints.size() == 3);
  68. BOOST_TEST(ints[0] == -1); // Failed conversion does not throw.
  69. BOOST_TEST(ints[1] == -1); // Failed conversion does not throw.
  70. BOOST_TEST(ints[2] == -1); // Failed conversion does not throw.
  71. //]
  72. }
  73. static
  74. void
  75. example3()
  76. {
  77. //[algorithm_example3
  78. /*`Deploying `boost::cnv::cstream` with better formatting capabilities yields
  79. better results with exception-throwing and non-throwing process-flows still supported:
  80. */
  81. boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  82. std::vector<int> ints;
  83. boost::cnv::cstream cnv;
  84. try
  85. {
  86. std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
  87. boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws))));
  88. BOOST_TEST(0 && "Never reached!");
  89. }
  90. catch (boost::bad_optional_access const&)
  91. {
  92. BOOST_TEST(ints.size() == 2); // Only the first two strings converted.
  93. BOOST_TEST(ints[0] == 5); // " 5"
  94. BOOST_TEST(ints[1] == 15); // "0XF"
  95. // "not an int" causes the exception thrown.
  96. }
  97. //]
  98. }
  99. static
  100. void
  101. example4()
  102. {
  103. boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  104. std::vector<int> ints;
  105. boost::cnv::cstream cnv;
  106. //[algorithm_example4
  107. std::transform(strs.begin(), strs.end(), std::back_inserter(ints),
  108. boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws))).value_or(-1));
  109. BOOST_TEST(ints.size() == 3);
  110. BOOST_TEST(ints[0] == 5);
  111. BOOST_TEST(ints[1] == 15);
  112. BOOST_TEST(ints[2] == -1); // Failed conversion
  113. /*`[important One notable difference in the deployment of `boost::cnv::cstream` with algorithms is
  114. the use of `boost::cref` (or `std::cref` in C++11).
  115. It needs to be remembered that with standard algorithms the deployed converter needs to be
  116. [@http://en.cppreference.com/w/cpp/named_req/TriviallyCopyable copyable] or
  117. [@http://en.cppreference.com/w/cpp/named_req/MoveAssignable movable (C++11)]
  118. and is, in fact, copied or moved by the respective algorithm before being used.
  119. Given that `std::cstringstream` is not copyable, `boost::cnv::cstream` is not copyable either.
  120. That limitation is routinely worked-around using `boost::ref` or `boost::cref`.]
  121. */
  122. //]
  123. }
  124. static
  125. void
  126. example5()
  127. {
  128. //[algorithm_example5
  129. /*`And now an example of algorithm-based integer-to-string formatted conversion with
  130. `std::hex`, `std::uppercase` and `std::showbase` formatting applied:
  131. */
  132. boost::array<int, 3> ints = {{ 15, 16, 17 }};
  133. std::vector<std::string> strs;
  134. boost::cnv::cstream cnv;
  135. cnv(std::hex)(std::uppercase)(std::showbase);
  136. std::transform(ints.begin(), ints.end(), std::back_inserter(strs),
  137. boost::cnv::apply<string>(boost::cref(cnv)));
  138. BOOST_TEST(strs.size() == 3);
  139. BOOST_TEST(strs[0] == "0XF"); // 15
  140. BOOST_TEST(strs[1] == "0X10"); // 16
  141. BOOST_TEST(strs[2] == "0X11"); // 17
  142. //]
  143. }
  144. int
  145. main(int, char const* [])
  146. {
  147. introduction();
  148. example1();
  149. example2();
  150. example3();
  151. example4();
  152. example5();
  153. return boost::report_errors();
  154. }