3 // Copyright (c) 2009-2014 Vladimir Batov.
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.
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
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.
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.
25 #ifndef BOOST_CONVERT_HPP
26 #define BOOST_CONVERT_HPP
28 #include <boost/convert/detail/is_fun.hpp>
29 #include <boost/ref.hpp>
33 namespace detail { enum throw_on_failure {}; }
35 /// @details The boost::throw_on_failure is the name of an object of the
36 /// boost::detail::throw_on_failure type that is used to indicate
37 /// desired exception-throwing behavior.
38 detail::throw_on_failure const throw_on_failure = detail::throw_on_failure(0);
42 template<typename, typename, typename> struct reference;
46 /// @brief Boost.Convert main deployment interface
47 /// @param[in] value_in Value of the TypeIn type to be converted to the TyeOut type
48 /// @param[in] converter Converter to be used for conversion
49 /// @return boost::optional<TypeOut> result of conversion together with the indication of
50 /// success or failure of the conversion request.
51 /// @details For example,
53 /// boost::cnv::cstream cnv;
55 /// boost::optional<int> i = boost::convert<int>("12", cnv);
56 /// boost::optional<string> s = boost::convert<string>(123.456, cnv);
59 template<typename TypeOut, typename TypeIn, typename Converter>
60 boost::optional<TypeOut>
61 convert(TypeIn const& value_in, Converter const& converter)
63 optional<TypeOut> result;
64 boost::unwrap_ref(converter)(value_in, result);
68 namespace cnv { namespace detail
70 template<typename TypeOut, typename TypeIn, typename Converter =boost::cnv::by_default>
71 struct delayed_resolution
73 static optional<TypeOut> convert(TypeIn const& value_in)
75 return boost::convert<TypeOut>(value_in, Converter());
79 /// @brief Boost.Convert deployment interface with the default converter
80 /// @details For example,
82 /// struct boost::cnv::by_default : public boost::cnv::cstream {};
84 /// // boost::cnv::cstream (through boost::cnv::by_default) is deployed
85 /// // as the default converter when no converter is provided explicitly.
86 /// boost::optional<int> i = boost::convert<int>("12");
87 /// boost::optional<string> s = boost::convert<string>(123.456);
90 template<typename TypeOut, typename TypeIn>
91 boost::optional<TypeOut>
92 convert(TypeIn const& value_in)
94 return cnv::detail::delayed_resolution<TypeOut, TypeIn>::convert(value_in);
100 /// @brief Boost.Convert non-optional deployment interface
102 template<typename TypeOut, typename TypeIn, typename Converter>
104 convert(TypeIn const& value_in, Converter const& converter, boost::detail::throw_on_failure)
106 return convert<TypeOut>(value_in, converter).value();
109 template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
110 typename enable_if<is_convertible<Fallback, TypeOut>, TypeOut>::type
111 convert(TypeIn const& value_in, Converter const& converter, Fallback const& fallback)
113 return convert<TypeOut>(value_in, converter).value_or(fallback);
116 template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
117 typename enable_if<cnv::is_fun<Fallback, TypeOut>, TypeOut>::type
118 convert(TypeIn const& value_in, Converter const& converter, Fallback fallback)
120 return convert<TypeOut>(value_in, converter).value_or_eval(fallback);
124 namespace boost { namespace cnv
126 template<typename Converter, typename TypeOut, typename TypeIn>
129 typedef reference this_type;
131 reference(Converter const& cnv) : converter_(cnv) {}
133 #ifdef BOOST_CONVERT_CXX11
134 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
138 value_or(TypeOut const& fallback)
140 return (fallback_ = fallback, *this);
144 operator()(TypeIn const& value_in)
146 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
147 return result ? result.get() : fallback_.value();
152 Converter converter_;
153 optional<TypeOut> fallback_;
155 template<typename Converter, typename TypeOut>
156 struct reference<Converter, TypeOut, void>
158 typedef reference this_type;
160 reference(Converter const& cnv) : converter_(cnv) {}
162 #ifdef BOOST_CONVERT_CXX11
163 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
167 value_or(TypeOut const& fallback)
169 return (fallback_ = fallback, *this);
172 template<typename TypeIn>
174 operator()(TypeIn const& value_in)
176 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
177 return result ? result.get() : fallback_.value();
182 Converter converter_;
183 optional<TypeOut> fallback_;
186 /// @brief Boost.Convert deployment interface with algorithms
187 /// @details For example,
189 /// boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
190 /// std::vector<int> ints;
191 /// boost::cnv::cstream cnv;
193 /// cnv(std::hex)(std::skipws);
198 /// std::back_inserter(ints),
199 /// boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
202 template<typename TypeOut, typename TypeIn, typename Converter>
203 reference<Converter, TypeOut, TypeIn>
204 apply(Converter const& cnv)
206 return cnv::reference<Converter, TypeOut, TypeIn>(cnv);
208 template<typename TypeOut, typename Converter>
209 reference<Converter, TypeOut, void>
210 apply(Converter const& cnv)
212 return cnv::reference<Converter, TypeOut, void>(cnv);
216 #endif // BOOST_CONVERT_HPP