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

source code of boost/libs/lexical_cast/test/stream_detection_test.cpp