3 // Copyright (c) 2009-2016 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 boost::throw_on_failure is the 'tag' object
36 /// to request the exception-throwing behavior.
37 detail::throw_on_failure const throw_on_failure = detail::throw_on_failure(0);
41 template<typename, typename, typename> struct reference;
45 /// @brief Boost.Convert main deployment interface
46 /// @param[in] value_in Value of the TypeIn type to be converted to the TypeOut type
47 /// @param[in] converter Converter to be used for conversion
48 /// @return boost::optional<TypeOut> result of conversion together with the indication of
49 /// success or failure of the conversion request.
50 /// @details For example,
52 /// boost::cnv::cstream cnv;
54 /// boost::optional<int> i = boost::convert<int>("12", cnv);
55 /// boost::optional<string> s = boost::convert<string>(123.456, cnv);
58 template<typename TypeOut, typename TypeIn, typename Converter>
59 boost::optional<TypeOut>
60 convert(TypeIn const& value_in, Converter const& converter)
62 optional<TypeOut> result;
63 boost::unwrap_ref(converter)(value_in, result);
67 namespace cnv { namespace detail
69 template<typename TypeOut, typename TypeIn, typename Converter =boost::cnv::by_default>
70 struct delayed_resolution
72 static optional<TypeOut> convert(TypeIn const& value_in)
74 return boost::convert<TypeOut>(value_in, Converter());
78 /// @brief Boost.Convert deployment interface with the default converter
79 /// @details For example,
81 /// struct boost::cnv::by_default : boost::cnv::cstream {};
83 /// // boost::cnv::cstream (through boost::cnv::by_default) is deployed
84 /// // as the default converter when no converter is provided explicitly.
85 /// boost::optional<int> i = boost::convert<int>("12");
86 /// boost::optional<string> s = boost::convert<string>(123.456);
89 template<typename TypeOut, typename TypeIn>
90 boost::optional<TypeOut>
91 convert(TypeIn const& value_in)
93 return cnv::detail::delayed_resolution<TypeOut, TypeIn>::convert(value_in);
99 /// @brief Boost.Convert non-optional deployment interface
101 template<typename TypeOut, typename TypeIn, typename Converter>
103 convert(TypeIn const& value_in, Converter const& converter, boost::detail::throw_on_failure)
105 return convert<TypeOut>(value_in, converter).value();
108 template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
109 typename enable_if<is_convertible<Fallback, TypeOut>, TypeOut>::type
110 convert(TypeIn const& value_in, Converter const& converter, Fallback const& fallback)
112 return convert<TypeOut>(value_in, converter).value_or(fallback);
115 template<typename TypeOut, typename TypeIn, typename Converter, typename Fallback>
116 typename enable_if<cnv::is_fun<Fallback, TypeOut>, TypeOut>::type
117 convert(TypeIn const& value_in, Converter const& converter, Fallback fallback)
119 return convert<TypeOut>(value_in, converter).value_or_eval(fallback);
123 namespace boost { namespace cnv
125 template<typename Converter, typename TypeOut, typename TypeIn>
128 typedef reference this_type;
130 reference(Converter const& cnv) : converter_(cnv) {}
132 #ifdef BOOST_CONVERT_CXX11
133 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
137 value_or(TypeOut const& fallback)
139 return (fallback_ = fallback, *this);
143 operator()(TypeIn const& value_in)
145 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
146 return result ? result.get() : fallback_.value();
151 Converter converter_;
152 optional<TypeOut> fallback_;
154 template<typename Converter, typename TypeOut>
155 struct reference<Converter, TypeOut, void>
157 typedef reference this_type;
159 reference(Converter const& cnv) : converter_(cnv) {}
161 #ifdef BOOST_CONVERT_CXX11
162 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
166 value_or(TypeOut const& fallback)
168 return (fallback_ = fallback, *this);
171 template<typename TypeIn>
173 operator()(TypeIn const& value_in)
175 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
176 return result ? result.get() : fallback_.value();
181 Converter converter_;
182 optional<TypeOut> fallback_;
185 /// @brief Boost.Convert deployment interface with algorithms
186 /// @details For example,
188 /// boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
189 /// std::vector<int> ints;
190 /// boost::cnv::cstream cnv;
192 /// cnv(std::hex)(std::skipws);
197 /// std::back_inserter(ints),
198 /// boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
201 template<typename TypeOut, typename TypeIn, typename Converter>
202 reference<Converter, TypeOut, TypeIn>
203 apply(Converter const& cnv)
205 return cnv::reference<Converter, TypeOut, TypeIn>(cnv);
207 template<typename TypeOut, typename Converter>
208 reference<Converter, TypeOut, void>
209 apply(Converter const& cnv)
211 return cnv::reference<Converter, TypeOut, void>(cnv);
215 #endif // BOOST_CONVERT_HPP