]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
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 | ||
31 | namespace 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 | ||
98 | namespace 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 | ||
124 | namespace 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 |