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