convert.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /// @file
  2. // Boost.Convert
  3. // Copyright (c) 2009-2014 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 The boost::throw_on_failure is the name of an object of the
  32. /// boost::detail::throw_on_failure type that is used to indicate
  33. /// desired exception-throwing behavior.
  34. detail::throw_on_failure const throw_on_failure = detail::throw_on_failure(0);
  35. namespace cnv
  36. {
  37. template<typename, typename, typename> struct reference;
  38. struct by_default;
  39. }
  40. /// @brief Boost.Convert main deployment interface
  41. /// @param[in] value_in Value of the TypeIn type to be converted to the TyeOut type
  42. /// @param[in] converter Converter to be used for conversion
  43. /// @return boost::optional<TypeOut> result of conversion together with the indication of
  44. /// success or failure of the conversion request.
  45. /// @details For example,
  46. /// @code
  47. /// boost::cnv::cstream cnv;
  48. ///
  49. /// boost::optional<int> i = boost::convert<int>("12", cnv);
  50. /// boost::optional<string> s = boost::convert<string>(123.456, cnv);
  51. /// @endcode
  52. template<typename TypeOut, typename TypeIn, typename Converter>
  53. boost::optional<TypeOut>
  54. convert(TypeIn const& value_in, Converter const& converter)
  55. {
  56. optional<TypeOut> result;
  57. boost::unwrap_ref(converter)(value_in, result);
  58. return result;
  59. }
  60. namespace cnv { namespace detail
  61. {
  62. template<typename TypeOut, typename TypeIn, typename Converter =boost::cnv::by_default>
  63. struct delayed_resolution
  64. {
  65. static optional<TypeOut> convert(TypeIn const& value_in)
  66. {
  67. return boost::convert<TypeOut>(value_in, Converter());
  68. }
  69. };
  70. }}
  71. /// @brief Boost.Convert deployment interface with the default converter
  72. /// @details For example,
  73. /// @code
  74. /// struct boost::cnv::by_default : public boost::cnv::cstream {};
  75. ///
  76. /// // boost::cnv::cstream (through boost::cnv::by_default) is deployed
  77. /// // as the default converter when no converter is provided explicitly.
  78. /// boost::optional<int> i = boost::convert<int>("12");
  79. /// boost::optional<string> s = boost::convert<string>(123.456);
  80. /// @endcode
  81. template<typename TypeOut, typename TypeIn>
  82. boost::optional<TypeOut>
  83. convert(TypeIn const& value_in)
  84. {
  85. return cnv::detail::delayed_resolution<TypeOut, TypeIn>::convert(value_in);
  86. }
  87. }
  88. namespace boost
  89. {
  90. /// @brief Boost.Convert non-optional deployment interface
  91. template<typename TypeOut, typename TypeIn, typename Converter>
  92. TypeOut
  93. convert(TypeIn const& value_in, Converter const& converter, boost::detail::throw_on_failure)
  94. {
  95. return convert<TypeOut>(value_in, converter).value();
  96. }
  97. template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
  98. typename enable_if<is_convertible<Fallback, TypeOut>, TypeOut>::type
  99. convert(TypeIn const& value_in, Converter const& converter, Fallback const& fallback)
  100. {
  101. return convert<TypeOut>(value_in, converter).value_or(fallback);
  102. }
  103. template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
  104. typename enable_if<cnv::is_fun<Fallback, TypeOut>, TypeOut>::type
  105. convert(TypeIn const& value_in, Converter const& converter, Fallback fallback)
  106. {
  107. return convert<TypeOut>(value_in, converter).value_or_eval(fallback);
  108. }
  109. }
  110. namespace boost { namespace cnv
  111. {
  112. template<typename Converter, typename TypeOut, typename TypeIn>
  113. struct reference
  114. {
  115. typedef reference this_type;
  116. reference(Converter const& cnv) : converter_(cnv) {}
  117. #ifdef BOOST_CONVERT_CXX11
  118. reference(Converter&& cnv) : converter_(std::move(cnv)) {}
  119. #endif
  120. this_type&
  121. value_or(TypeOut const& fallback)
  122. {
  123. return (fallback_ = fallback, *this);
  124. }
  125. TypeOut
  126. operator()(TypeIn const& value_in)
  127. {
  128. optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
  129. return result ? result.get() : fallback_.value();
  130. }
  131. private:
  132. Converter converter_;
  133. optional<TypeOut> fallback_;
  134. };
  135. template<typename Converter, typename TypeOut>
  136. struct reference<Converter, TypeOut, void>
  137. {
  138. typedef reference this_type;
  139. reference(Converter const& cnv) : converter_(cnv) {}
  140. #ifdef BOOST_CONVERT_CXX11
  141. reference(Converter&& cnv) : converter_(std::move(cnv)) {}
  142. #endif
  143. this_type&
  144. value_or(TypeOut const& fallback)
  145. {
  146. return (fallback_ = fallback, *this);
  147. }
  148. template<typename TypeIn>
  149. TypeOut
  150. operator()(TypeIn const& value_in)
  151. {
  152. optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
  153. return result ? result.get() : fallback_.value();
  154. }
  155. private:
  156. Converter converter_;
  157. optional<TypeOut> fallback_;
  158. };
  159. /// @brief Boost.Convert deployment interface with algorithms
  160. /// @details For example,
  161. /// @code
  162. /// boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
  163. /// std::vector<int> ints;
  164. /// boost::cnv::cstream cnv;
  165. ///
  166. /// cnv(std::hex)(std::skipws);
  167. ///
  168. /// std::transform(
  169. /// strs.begin(),
  170. /// strs.end(),
  171. /// std::back_inserter(ints),
  172. /// boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
  173. /// @endcode
  174. template<typename TypeOut, typename TypeIn, typename Converter>
  175. reference<Converter, TypeOut, TypeIn>
  176. apply(Converter const& cnv)
  177. {
  178. return cnv::reference<Converter, TypeOut, TypeIn>(cnv);
  179. }
  180. template<typename TypeOut, typename Converter>
  181. reference<Converter, TypeOut, void>
  182. apply(Converter const& cnv)
  183. {
  184. return cnv::reference<Converter, TypeOut, void>(cnv);
  185. }
  186. }}
  187. #endif // BOOST_CONVERT_HPP