1 // Unit test for boost::lexical_cast.
2 //
3 // See http://www.boost.org for most recent version, including documentation.
4 //
5 // Copyright Antony Polukhin, 2011-2012.
6 //
7 // Distributed under the Boost
8 // Software License, Version 1.0. (See accompanying file
9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
10
11
12 #include <boost/config.hpp>
13 #include <boost/test/unit_test.hpp>
14
15 #include <boost/lexical_cast.hpp>
16
17 #include <iostream>
18
19
20 ///////////////////////// char streamable classes ///////////////////////////////////////////
21
22 struct streamable_easy { enum ENU {value = 0}; };
operator <<(std::ostream & ostr,const streamable_easy &)23 std::ostream& operator << (std::ostream& ostr, const streamable_easy&) {
24 return ostr << streamable_easy::value;
25 }
operator >>(std::istream & istr,const streamable_easy &)26 std::istream& operator >> (std::istream& istr, const streamable_easy&) {
27 int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value);
28 return istr;
29 }
30
31 struct streamable_medium { enum ENU {value = 1}; };
32 template <class CharT>
33 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT>&>::type
operator <<(std::basic_ostream<CharT> & ostr,const streamable_medium &)34 operator << (std::basic_ostream<CharT>& ostr, const streamable_medium&) {
35 return ostr << streamable_medium::value;
36 }
37 template <class CharT>
38 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT>&>::type
operator >>(std::basic_istream<CharT> & istr,const streamable_medium &)39 operator >> (std::basic_istream<CharT>& istr, const streamable_medium&) {
40 int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value);
41 return istr;
42 }
43
44 struct streamable_hard { enum ENU {value = 2}; };
45 template <class CharT, class TraitsT>
46 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT, TraitsT>&>::type
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const streamable_hard &)47 operator << (std::basic_ostream<CharT, TraitsT>& ostr, const streamable_hard&) {
48 return ostr << streamable_hard::value;
49 }
50 template <class CharT, class TraitsT>
51 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT, TraitsT>&>::type
operator >>(std::basic_istream<CharT,TraitsT> & istr,const streamable_hard &)52 operator >> (std::basic_istream<CharT, TraitsT>& istr, const streamable_hard&) {
53 int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value);
54 return istr;
55 }
56
57 struct streamable_hard2 { enum ENU {value = 3}; };
58 template <class TraitsT>
operator <<(std::basic_ostream<char,TraitsT> & ostr,const streamable_hard2 &)59 std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const streamable_hard2&) {
60 return ostr << streamable_hard2::value;
61 }
62 template <class TraitsT>
operator >>(std::basic_istream<char,TraitsT> & istr,const streamable_hard2 &)63 std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const streamable_hard2&) {
64 int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value);
65 return istr;
66 }
67
68
69 ///////////////////////// wchar_t streamable classes ///////////////////////////////////////////
70
71 struct wstreamable_easy { enum ENU {value = 4}; };
operator <<(std::wostream & ostr,const wstreamable_easy &)72 std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) {
73 return ostr << wstreamable_easy::value;
74 }
operator >>(std::wistream & istr,const wstreamable_easy &)75 std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) {
76 int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value);
77 return istr;
78 }
79
80 struct wstreamable_medium { enum ENU {value = 5}; };
81 template <class CharT>
82 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT>& >::type
operator <<(std::basic_ostream<CharT> & ostr,const wstreamable_medium &)83 operator << (std::basic_ostream<CharT>& ostr, const wstreamable_medium&) {
84 return ostr << wstreamable_medium::value;
85 }
86 template <class CharT>
87 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT>& >::type
operator >>(std::basic_istream<CharT> & istr,const wstreamable_medium &)88 operator >> (std::basic_istream<CharT>& istr, const wstreamable_medium&) {
89 int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value);
90 return istr;
91 }
92
93 struct wstreamable_hard { enum ENU {value = 6}; };
94 template <class CharT, class TraitsT>
95 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT, TraitsT>&>::type
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const wstreamable_hard &)96 operator << (std::basic_ostream<CharT, TraitsT>& ostr, const wstreamable_hard&) {
97 return ostr << wstreamable_hard::value;
98 }
99 template <class CharT, class TraitsT>
100 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT, TraitsT>&>::type
operator >>(std::basic_istream<CharT,TraitsT> & istr,const wstreamable_hard &)101 operator >> (std::basic_istream<CharT, TraitsT>& istr, const wstreamable_hard&) {
102 int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value);
103 return istr;
104 }
105
106 struct wstreamable_hard2 { enum ENU {value = 7}; };
107 template <class TraitsT>
operator <<(std::basic_ostream<wchar_t,TraitsT> & ostr,const wstreamable_hard2 &)108 std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const wstreamable_hard2&) {
109 return ostr << wstreamable_hard2::value;
110 }
111 template <class TraitsT>
operator >>(std::basic_istream<wchar_t,TraitsT> & istr,const wstreamable_hard2 &)112 std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const wstreamable_hard2&) {
113 int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value);
114 return istr;
115 }
116
117 ///////////////////////// char and wchar_t streamable classes ///////////////////////////////////////////
118
119
120 struct bistreamable_easy { enum ENU {value = 8}; };
operator <<(std::ostream & ostr,const bistreamable_easy &)121 std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) {
122 return ostr << bistreamable_easy::value;
123 }
operator >>(std::istream & istr,const bistreamable_easy &)124 std::istream& operator >> (std::istream& istr, const bistreamable_easy&) {
125 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value);
126 return istr;
127 }
128
operator <<(std::wostream & ostr,const bistreamable_easy &)129 std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) {
130 return ostr << bistreamable_easy::value + 100;
131 }
operator >>(std::wistream & istr,const bistreamable_easy &)132 std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) {
133 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100);
134 return istr;
135 }
136
137 struct bistreamable_medium { enum ENU {value = 9}; };
138 template <class CharT>
operator <<(std::basic_ostream<CharT> & ostr,const bistreamable_medium &)139 std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& ostr, const bistreamable_medium&) {
140 return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100);
141 }
142 template <class CharT>
operator >>(std::basic_istream<CharT> & istr,const bistreamable_medium &)143 std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, const bistreamable_medium&) {
144 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100));
145 return istr;
146 }
147
148 struct bistreamable_hard { enum ENU {value = 10}; };
149 template <class CharT, class TraitsT>
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const bistreamable_hard &)150 std::basic_ostream<CharT, TraitsT>& operator << (std::basic_ostream<CharT, TraitsT>& ostr, const bistreamable_hard&) {
151 return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100);
152 }
153 template <class CharT, class TraitsT>
operator >>(std::basic_istream<CharT,TraitsT> & istr,const bistreamable_hard &)154 std::basic_istream<CharT, TraitsT>& operator >> (std::basic_istream<CharT, TraitsT>& istr, const bistreamable_hard&) {
155 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100));
156 return istr;
157 }
158
159 struct bistreamable_hard2 { enum ENU {value = 11}; };
160 template <class TraitsT>
operator <<(std::basic_ostream<char,TraitsT> & ostr,const bistreamable_hard2 &)161 std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const bistreamable_hard2&) {
162 return ostr << bistreamable_hard2::value;
163 }
164 template <class TraitsT>
operator >>(std::basic_istream<char,TraitsT> & istr,const bistreamable_hard2 &)165 std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const bistreamable_hard2&) {
166 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value);
167 return istr;
168 }
169
170 template <class TraitsT>
operator <<(std::basic_ostream<wchar_t,TraitsT> & ostr,const bistreamable_hard2 &)171 std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const bistreamable_hard2&) {
172 return ostr << bistreamable_hard2::value + 100;
173 }
174 template <class TraitsT>
operator >>(std::basic_istream<wchar_t,TraitsT> & istr,const bistreamable_hard2 &)175 std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const bistreamable_hard2&) {
176 int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100);
177 return istr;
178 }
179
180
181 void test_ostream_character_detection();
182 void test_istream_character_detection();
183 void test_mixed_stream_character_detection();
184
init_unit_test_suite(int,char * [])185 boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
186 {
187 boost::unit_test::test_suite *suite =
188 BOOST_TEST_SUITE("lexical_cast stream character detection");
189 suite->add(BOOST_TEST_CASE(&test_ostream_character_detection));
190 suite->add(BOOST_TEST_CASE(&test_istream_character_detection));
191 suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection));
192
193 return suite;
194 }
195
196 template <class T>
test_ostr_impl()197 static void test_ostr_impl() {
198 T streamable;
199 BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
200 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
201 }
202
203 template <class T>
test_wostr_impl()204 static void test_wostr_impl() {
205 T streamable;
206 BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
207 // BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable)); // Shall not compile???
208 BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value) == boost::lexical_cast<std::wstring>(streamable));
209 }
210
211 template <class T>
test_bistr_impl()212 static void test_bistr_impl() {
213 T streamable;
214
215 BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
216 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
217
218 BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value + 100) == boost::lexical_cast<std::wstring>(streamable));
219 }
220
test_ostream_character_detection()221 void test_ostream_character_detection() {
222 test_ostr_impl<streamable_easy>();
223 test_ostr_impl<streamable_medium>();
224 test_ostr_impl<streamable_hard>();
225 test_ostr_impl<streamable_hard2>();
226
227 test_wostr_impl<wstreamable_easy>();
228 test_wostr_impl<wstreamable_medium>();
229 test_wostr_impl<wstreamable_hard>();
230 test_wostr_impl<wstreamable_hard2>();
231
232 test_bistr_impl<bistreamable_easy>();
233 test_bistr_impl<bistreamable_medium>();
234 test_bistr_impl<bistreamable_hard>();
235 test_bistr_impl<bistreamable_hard2>();
236 }
237
238
239 template <class T>
test_istr_impl()240 static void test_istr_impl() {
241 boost::lexical_cast<T>(T::value);
242 boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
243 }
244
245 template <class T>
test_wistr_impl()246 static void test_wistr_impl() {
247 boost::lexical_cast<T>(T::value);
248 //boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value)); // Shall not compile???
249 boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value));
250 }
251
252 template <class T>
test_bistr_instr_impl()253 static void test_bistr_instr_impl() {
254 boost::lexical_cast<T>(T::value);
255 boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
256 boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value + 100));
257 }
258
test_istream_character_detection()259 void test_istream_character_detection() {
260 test_istr_impl<streamable_easy>();
261 test_istr_impl<streamable_medium>();
262 test_istr_impl<streamable_hard>();
263 test_istr_impl<streamable_hard2>();
264
265 test_wistr_impl<wstreamable_easy>();
266 test_wistr_impl<wstreamable_medium>();
267 test_wistr_impl<wstreamable_hard>();
268 test_wistr_impl<wstreamable_hard2>();
269
270 test_bistr_instr_impl<bistreamable_easy>();
271 test_bistr_instr_impl<bistreamable_medium>();
272 test_bistr_instr_impl<bistreamable_hard>();
273 test_bistr_instr_impl<bistreamable_hard2>();
274 }
275
276
277
278
279
280
281 struct wistreamble_ostreamable { enum ENU {value = 200}; };
operator <<(std::ostream & ostr,const wistreamble_ostreamable &)282 std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) {
283 return ostr << wistreamble_ostreamable::value;
284 }
operator >>(std::wistream & istr,const wistreamble_ostreamable &)285 std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) {
286 int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value);
287 return istr;
288 }
289
290 struct istreamble_wostreamable { enum ENU {value = 201}; };
operator <<(std::wostream & ostr,const istreamble_wostreamable &)291 std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) {
292 return ostr << istreamble_wostreamable::value;
293 }
operator >>(std::istream & istr,const istreamble_wostreamable &)294 std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) {
295 int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value);
296 return istr;
297 }
298
test_mixed_stream_character_detection()299 void test_mixed_stream_character_detection() {
300 //boost::lexical_cast<std::wstring>(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION!
301
302 boost::lexical_cast<wistreamble_ostreamable>(wistreamble_ostreamable::value);
303 BOOST_CHECK_EQUAL(boost::lexical_cast<int>(wistreamble_ostreamable()), wistreamble_ostreamable::value);
304
305 boost::lexical_cast<istreamble_wostreamable>(istreamble_wostreamable::value);
306 BOOST_CHECK_EQUAL(boost::lexical_cast<int>(istreamble_wostreamable()), istreamble_wostreamable::value);
307 }
308