convert.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /// @file
  2. // Boost.Convert
  3. // Copyright (c) 2009-2016 Vladimir Batov.
  4. //
  5. // Many thanks to Julian Gonggrijp, Rob Stewart, Andrzej Krzemienski, Matus Chochlik, Jeroen Habraken,
  6. // Hartmut Kaiser, Joel De Guzman, Thijs (M.A.) van den Berg, Roland Bock, Gavin Lambert, Paul Bristow,
  7. // Alex Hagen-Zanker, Christopher Kormanyos for taking part in the Boost.Convert review.
  8. //
  9. // Special thanks to:
  10. //
  11. // 1. Alex Hagen-Zanker, Roland Bock, Rob Stewart for their considerable contributions to the design
  12. // and implementation of the library;
  13. // 2. Andrzej Krzemienski for helping to partition responsibilities and to ultimately pave
  14. // the way for the boost::optional and future std::tr2::optional deployment;
  15. // 3. Edward Diener the Boost Review Manager for helping with the converters' design, his continuous
  16. // involvement, technical and administrative help, guidance and advice;
  17. // 4. Joel De Guzman, Rob Stewart and Alex Hagen-Zanker for making sure the performance tests work
  18. // as they should;
  19. // 5. Paul Bristow for helping great deal with the documentation;
  20. // 6. Kevlin Henney and Dave Abrahams for their lexical_cast-related insights and explanations.
  21. //
  22. // Use, modification and distribution are subject to the Boost Software License,
  23. // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
  24. #ifndef BOOST_CONVERT_HPP
  25. #define BOOST_CONVERT_HPP
  26. #include <boost/convert/detail/is_fun.hpp>
  27. #include <boost/ref.hpp>
  28. namespace boost
  29. {
  30. namespace detail { enum throw_on_failure {}; }
  31. /// @details boost::throw_on_failure is the 'tag' object
  32. /// to request the exception-throwing behavior.
  33. detail::throw_on_failure const throw_on_failure = detail::throw_on_failure(0);
  34. namespace cnv
  35. {
  36. template<typename, typename, typename> struct reference;
  37. struct by_default;
  38. }
  39. /// @brief Boost.Convert main deployment interface
  40. /// @param[in] value_in Value of the TypeIn type to be converted to the TypeOut type
  41. /// @param[in] converter Converter to be used for conversion
  42. /// @return boost::optional<TypeOut> result of conversion together with the indication of
  43. /// success or failure of the conversion request.
  44. /// @details For example,
  45. /// @code
  46. /// boost::cnv::cstream cnv;
  47. ///
  48. /// boost::optional<int> i = boost::convert<int>("12", cnv);
  49. /// boost::optional<string> s = boost::convert<string>(123.456, cnv);
  50. /// @endcode
  51. template<typename TypeOut, typename TypeIn, typename Converter>
  52. boost::optional<TypeOut>
  53. convert(TypeIn const& value_in, Converter const& converter)
  54. {
  55. optional<TypeOut> result;
  56. boost::unwrap_ref(converter)(value_in, result);
  57. return result;
  58. }
  59. namespace cnv { namespace detail
  60. {
  61. template<typename TypeOut, typename TypeIn, typename Converter =boost::cnv::by_default>
  62. struct delayed_resolution
  63. {
  64. static optional<TypeOut> convert(TypeIn const& value_in)
  65. {
  66. return boost::convert<TypeOut>(value_in, Converter());
  67. }
  68. };
  69. }}
  70. /// @brief Boost.Convert deployment interface with the default converter
  71. /// @details For example,
  72. /// @code
  73. /// struct boost::cnv::by_default : boost::cnv::cstream {};
  74. ///
  75. /// // boost::cnv::cstream (through boost::cnv::by_default) is deployed
  76. /// // as the default converter when no converter is provided explicitly.
  77. /// boost::optional<int> i = boost::convert<int>("12");
  78. /// boost::optional<string> s = boost::convert<string>(123.456);
  79. /// @endcode
  80. template<typename TypeOut, typename TypeIn>
  81. boost::optional<TypeOut>
  82. convert(TypeIn const& value_in)
  83. {
  84. return cnv::detail::delayed_resolution<TypeOut, TypeIn>::convert(value_in);
  85. }
  86. }
  87. namespace boost
  88. {
  89. /// @brief Boost.Convert non-optional deployment interface
  90. template<typename TypeOut, typename TypeIn, typename Converter>
  91. TypeOut
  92. convert(TypeIn const& value_in, Converter const& converter, boost::detail::throw_on_failure)
  93. {
  94. return convert<TypeOut>(value_in, converter).value();
  95. }
  96. template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
  97. typename enable_if<is_convertible<Fallback, TypeOut>, TypeOut>::type
  98. convert(TypeIn const& value_in, Converter const& converter, Fallback const& fallback)
  99. {
  100. return convert<TypeOut>(value_in, converter).value_or(fallback);
  101. }
  102. template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
  103. typename enable_if<cnv::is_fun<Fallback, TypeOut>, TypeOut>::type
  104. convert(TypeIn const& value_in, Converter const& converter, Fallback fallback)
  105. {
  106. return convert<TypeOut>(value_in, converter).value_or_eval(fallback);
  107. }
  108. }
  109. namespace boost { namespace cnv
  110. {
  111. template<typename Converter, typename TypeOut, typename TypeIn>
  112. struct reference
  113. {
  114. typedef reference this_type;
  115. reference(Converter const& cnv) : converter_(cnv) {}
  116. #ifdef BOOST_CONVERT_CXX11
  117. reference(Converter&& cnv) : converter_(std::move(cnv)) {}
  118. #endif
  119. this_type&
  120. value_or(TypeOut const& fallback)
  121. {
  122. return (fallback_ = fallback, *this);
  123. }
  124. TypeOut
  125. operator()(TypeIn const& value_in)
  126. {
  127. optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
  128. return result ? result.get() : fallback_.value();
  129. }
  130. private:
  131. Converter converter_;
  132. optional<TypeOut> fallback_;
  133. };
  134. template<typename Converter, typename TypeOut>
  135. struct reference<Converter, TypeOut, void>
  136. {
  137. typedef reference this_type;
  138. reference(Converter const& cnv) : converter_(cnv) {}
  139. #ifdef BOOST_CONVERT_CXX11
  140. reference(Converter&& cnv) : converter_(std::move(cnv)) {}
  141. #endif
  142. this_type&
  143. value_or(TypeOut const& fallback)
  144. {
  145. return (fallback_ = fallback, *this);
  146. }
  147. template<typename TypeIn>
  148. TypeOut
  149. operator()(TypeIn const& value_in)
  150. {
  151. optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
  152. return result ? result.get() : fallback_.value();
  153. }
  154. private:
  155. Converter converter_;
  156. optional<TypeOut> fallback_;
  157. };
  158. /// @brief Boost.Convert deployment interface with algorithms
  159. /// @details For example,
  160. /// @code
  161. /// boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  162. /// std::vector<int> ints;
  163. /// boost::cnv::cstream cnv;
  164. ///
  165. /// cnv(std::hex)(std::skipws);
  166. ///
  167. /// std::transform(
  168. /// strs.begin(),
  169. /// strs.end(),
  170. /// std::back_inserter(ints),
  171. /// boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
  172. /// @endcode
  173. template<typename TypeOut, typename TypeIn, typename Converter>
  174. reference<Converter, TypeOut, TypeIn>
  175. apply(Converter const& cnv)
  176. {
  177. return cnv::reference<Converter, TypeOut, TypeIn>(cnv);
  178. }
  179. template<typename TypeOut, typename Converter>
  180. reference<Converter, TypeOut, void>
  181. apply(Converter const& cnv)
  182. {
  183. return cnv::reference<Converter, TypeOut, void>(cnv);
  184. }
  185. }}
  186. #endif // BOOST_CONVERT_HPP