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
25#ifndef BOOST_CONVERT_HPP
26#define BOOST_CONVERT_HPP
27
28#include <boost/convert/detail/is_fun.hpp>
29#include <boost/ref.hpp>
30
31namespace boost
32{
33 namespace detail { enum throw_on_failure {}; }
34
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);
39
40 namespace cnv
41 {
42 template<typename, typename, typename> struct reference;
43 struct by_default;
44 }
45
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,
52 /// @code
53 /// boost::cnv::cstream cnv;
54 ///
55 /// boost::optional<int> i = boost::convert<int>("12", cnv);
56 /// boost::optional<string> s = boost::convert<string>(123.456, cnv);
57 /// @endcode
58
59 template<typename TypeOut, typename TypeIn, typename Converter>
60 boost::optional<TypeOut>
61 convert(TypeIn const& value_in, Converter const& converter)
62 {
63 optional<TypeOut> result;
64 boost::unwrap_ref(converter)(value_in, result);
65 return result;
66 }
67
68 namespace cnv { namespace detail
69 {
70 template<typename TypeOut, typename TypeIn, typename Converter =boost::cnv::by_default>
71 struct delayed_resolution
72 {
73 static optional<TypeOut> convert(TypeIn const& value_in)
74 {
75 return boost::convert<TypeOut>(value_in, Converter());
76 }
77 };
78 }}
79 /// @brief Boost.Convert deployment interface with the default converter
80 /// @details For example,
81 /// @code
82 /// struct boost::cnv::by_default : public boost::cnv::cstream {};
83 ///
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);
88 /// @endcode
89
90 template<typename TypeOut, typename TypeIn>
91 boost::optional<TypeOut>
92 convert(TypeIn const& value_in)
93 {
94 return cnv::detail::delayed_resolution<TypeOut, TypeIn>::convert(value_in);
95 }
96}
97
98namespace boost
99{
100 /// @brief Boost.Convert non-optional deployment interface
101
102 template<typename TypeOut, typename TypeIn, typename Converter>
103 TypeOut
104 convert(TypeIn const& value_in, Converter const& converter, boost::detail::throw_on_failure)
105 {
106 return convert<TypeOut>(value_in, converter).value();
107 }
108
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)
112 {
113 return convert<TypeOut>(value_in, converter).value_or(fallback);
114 }
115
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)
119 {
120 return convert<TypeOut>(value_in, converter).value_or_eval(fallback);
121 }
122}
123
124namespace boost { namespace cnv
125{
126 template<typename Converter, typename TypeOut, typename TypeIn>
127 struct reference
128 {
129 typedef reference this_type;
130
131 reference(Converter const& cnv) : converter_(cnv) {}
132
133#ifdef BOOST_CONVERT_CXX11
134 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
135#endif
136
137 this_type&
138 value_or(TypeOut const& fallback)
139 {
140 return (fallback_ = fallback, *this);
141 }
142
143 TypeOut
144 operator()(TypeIn const& value_in)
145 {
146 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
147 return result ? result.get() : fallback_.value();
148 }
149
150 private:
151
152 Converter converter_;
153 optional<TypeOut> fallback_;
154 };
155 template<typename Converter, typename TypeOut>
156 struct reference<Converter, TypeOut, void>
157 {
158 typedef reference this_type;
159
160 reference(Converter const& cnv) : converter_(cnv) {}
161
162#ifdef BOOST_CONVERT_CXX11
163 reference(Converter&& cnv) : converter_(std::move(cnv)) {}
164#endif
165
166 this_type&
167 value_or(TypeOut const& fallback)
168 {
169 return (fallback_ = fallback, *this);
170 }
171
172 template<typename TypeIn>
173 TypeOut
174 operator()(TypeIn const& value_in)
175 {
176 optional<TypeOut> result = convert<TypeOut>(value_in, converter_);
177 return result ? result.get() : fallback_.value();
178 }
179
180 private:
181
182 Converter converter_;
183 optional<TypeOut> fallback_;
184 };
185
186 /// @brief Boost.Convert deployment interface with algorithms
187 /// @details For example,
188 /// @code
189 /// boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }};
190 /// std::vector<int> ints;
191 /// boost::cnv::cstream cnv;
192 ///
193 /// cnv(std::hex)(std::skipws);
194 ///
195 /// std::transform(
196 /// strs.begin(),
197 /// strs.end(),
198 /// std::back_inserter(ints),
199 /// boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1));
200 /// @endcode
201
202 template<typename TypeOut, typename TypeIn, typename Converter>
203 reference<Converter, TypeOut, TypeIn>
204 apply(Converter const& cnv)
205 {
206 return cnv::reference<Converter, TypeOut, TypeIn>(cnv);
207 }
208 template<typename TypeOut, typename Converter>
209 reference<Converter, TypeOut, void>
210 apply(Converter const& cnv)
211 {
212 return cnv::reference<Converter, TypeOut, void>(cnv);
213 }
214}}
215
216#endif // BOOST_CONVERT_HPP
217

source code of boost/boost/convert.hpp