1// Unit test for boost::lexical_cast.
2//
3// See http://www.boost.org for most recent version, including documentation.
4//
5// Copyright Terje Sletteb and Kevlin Henney, 2005.
6// Copyright Alexander Nasonov, 2006.
7// Copyright Antony Polukhin, 2011-2024.
8//
9// Distributed under the Boost
10// Software License, Version 1.0. (See accompanying file
11// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
12//
13// Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it.
14
15//
16// We need this #define before any #includes: otherwise msvc will emit warnings
17// deep within std::string, resulting from our (perfectly legal) use of basic_string
18// with a custom traits class:
19//
20#define _SCL_SECURE_NO_WARNINGS
21
22#include <boost/lexical_cast.hpp>
23
24#include <boost/cstdint.hpp>
25
26#include <boost/core/lightweight_test.hpp>
27
28#include <boost/type_traits/integral_promotion.hpp>
29#include <boost/type_traits/make_unsigned.hpp>
30#include <string>
31#include <vector>
32#include <memory>
33
34#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
35 && !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
36#define LCAST_TEST_LONGLONG
37#endif
38
39#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
40#define BOOST_LCAST_NO_WCHAR_T
41#endif
42
43#if defined(BOOST_HAS_INT128) && !defined(BOOST_LEXICAL_CAST_TEST_NO_128_INTS)
44# define BOOST_LCAST_TEST_128 1
45#endif
46
47// Test all 65536 values if true:
48bool const lcast_test_small_integral_types_completely = false;
49
50// lcast_integral_test_counter: use when testing all values of an integral
51// types is not possible. Max. portable value is 32767.
52int const lcast_integral_test_counter=500;
53
54using namespace boost;
55
56template<class T, class CharT>
57void test_conversion_from_integral_to_char(CharT zero)
58{
59 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
60 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
61 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
62 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
63 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
64 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
65 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
66 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
67 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
68 BOOST_TEST(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
69
70 BOOST_TEST_THROWS(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
71
72 T t = (std::numeric_limits<T>::max)();
73 BOOST_TEST_THROWS(lexical_cast<CharT>(t), bad_lexical_cast);
74}
75
76template<class T, class CharT>
77void test_conversion_from_char_to_integral(CharT zero)
78{
79 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 0)) == static_cast<T>(0) );
80 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 1)) == static_cast<T>(1) );
81 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 2)) == static_cast<T>(2) );
82 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 3)) == static_cast<T>(3) );
83 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 4)) == static_cast<T>(4) );
84 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 5)) == static_cast<T>(5) );
85 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 6)) == static_cast<T>(6) );
86 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 7)) == static_cast<T>(7) );
87 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 8)) == static_cast<T>(8) );
88 BOOST_TEST(lexical_cast<T>( static_cast<CharT>(zero + 9)) == static_cast<T>(9) );
89
90 BOOST_TEST_THROWS(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
91 BOOST_TEST_THROWS(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
92}
93
94template<class T>
95void test_conversion_from_integral_to_integral()
96{
97 T t = 0;
98 BOOST_TEST(lexical_cast<T>(t) == t);
99
100 // Next two variables are used to suppress warnings.
101 int st = 32767; unsigned int ut = st;
102 t = st;
103 BOOST_TEST(lexical_cast<short>(t) == st);
104 BOOST_TEST(lexical_cast<unsigned short>(t) == ut);
105 BOOST_TEST(lexical_cast<int>(t) == st);
106 BOOST_TEST(lexical_cast<unsigned int>(t) == ut);
107 BOOST_TEST(lexical_cast<long>(t) == st);
108 BOOST_TEST(lexical_cast<unsigned long>(t) == ut);
109
110 t = (std::numeric_limits<T>::max)();
111 BOOST_TEST(lexical_cast<T>(t) == t);
112
113 t = (std::numeric_limits<T>::min)();
114 BOOST_TEST(lexical_cast<T>(t) == t);
115}
116
117
118
119
120// Replace "-,999" with "-999".
121template<class CharT>
122std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
123{
124 std::locale loc;
125 std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
126 std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
127
128 if(np.grouping().empty())
129 return str;
130
131 CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
132
133 if(str.find(prefix) != 0)
134 return str;
135
136 prefix[1] = CharT();
137 str.replace(0, 2, prefix);
138 return str;
139}
140
141template<class CharT, class T>
142std::basic_string<CharT> to_str(T t)
143{
144 std::basic_ostringstream<CharT> o;
145 o << t;
146 return to_str_gcc_workaround(o.str());
147}
148
149
150template<class T, class CharT>
151void test_conversion_from_integral_to_string(CharT)
152{
153 typedef std::numeric_limits<T> limits;
154 typedef std::basic_string<CharT> string_type;
155
156 T t;
157
158 t = (limits::min)();
159 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
160
161 t = (limits::max)();
162 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
163
164 if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
165 // min and max have already been tested.
166 for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
167 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
168 else
169 {
170 T const min_val = (limits::min)();
171 T const max_val = (limits::max)();
172 T const half_max_val = max_val / 2;
173 T const cnt = lcast_integral_test_counter; // to suppress warnings
174 T const counter = cnt < half_max_val ? cnt : half_max_val;
175
176 T i = 0;
177
178 // Test values around min:
179 t = min_val;
180 for(i = 0; i < counter; ++i, ++t)
181 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
182
183 // Test values around max:
184 t = max_val;
185 for(i = 0; i < counter; ++i, --t)
186 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
187
188 // Test values around zero:
189 if(limits::is_signed)
190 for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
191 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
192
193 // Test values around 100, 1000, 10000, ...
194 T ten_power = 100;
195 for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
196 {
197 // ten_power + 100 probably never overflows
198 for(t = ten_power - 100; t != ten_power + 100; ++t)
199 BOOST_TEST(lexical_cast<string_type>(t) == to_str<CharT>(t));
200 }
201 }
202}
203
204template<class T, class CharT>
205void test_conversion_from_string_to_integral(CharT)
206{
207 typedef std::numeric_limits<T> limits;
208 typedef std::basic_string<CharT> string_type;
209
210 string_type s;
211 string_type const zero = to_str<CharT>(0);
212 string_type const nine = to_str<CharT>(9);
213 T const min_val = (limits::min)();
214 T const max_val = (limits::max)();
215
216 s = to_str<CharT>(min_val);
217 BOOST_TEST_EQ(lexical_cast<T>(s), min_val);
218 if(limits::is_signed)
219 {
220 BOOST_TEST_THROWS(lexical_cast<T>(s + zero), bad_lexical_cast);
221 BOOST_TEST_THROWS(lexical_cast<T>(s + nine), bad_lexical_cast);
222 }
223
224 s = to_str<CharT>(max_val);
225 BOOST_TEST_EQ(lexical_cast<T>(s), max_val);
226 {
227 BOOST_TEST_THROWS(lexical_cast<T>(s + zero), bad_lexical_cast);
228 BOOST_TEST_THROWS(lexical_cast<T>(s + nine), bad_lexical_cast);
229
230 s = to_str<CharT>(max_val);
231 for (int i =1; i <=10; ++i) {
232 s[s.size()-1] += 1;
233 BOOST_TEST_THROWS(lexical_cast<T>( s ), bad_lexical_cast);
234 }
235
236 s = to_str<CharT>(max_val);
237 std::locale loc;
238 typedef std::numpunct<char> numpunct;
239 if ( BOOST_USE_FACET(numpunct, loc).grouping().empty() ) {
240 // Following tests work well for locale C
241 BOOST_TEST_EQ(lexical_cast<T>(to_str<CharT>(0)+s), max_val);
242 BOOST_TEST_EQ(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
243 BOOST_TEST_EQ(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
244 }
245
246 for (int i =1; i <=256; ++i) {
247 BOOST_TEST_THROWS(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
248 }
249
250 typedef typename boost::integral_promotion<T>::type promoted;
251 if ( !(boost::is_same<T, promoted>::value) )
252 {
253 promoted prom = max_val;
254 s = to_str<CharT>(max_val);
255 for (int i =1; i <=256; ++i) {
256 BOOST_TEST_THROWS(lexical_cast<T>( to_str<CharT>(prom+i) ), bad_lexical_cast);
257 BOOST_TEST_THROWS(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
258 }
259 }
260 }
261
262 if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
263 // min and max have already been tested.
264 for(T t = 1 + min_val; t != max_val; ++t)
265 BOOST_TEST(lexical_cast<T>(to_str<CharT>(t)) == t);
266 else
267 {
268 T const half_max_val = max_val / 2;
269 T const cnt = lcast_integral_test_counter; // to suppress warnings
270 T const counter = cnt < half_max_val ? cnt : half_max_val;
271
272 T t;
273 T i;
274
275 // Test values around min:
276 t = min_val;
277 for(i = 0; i < counter; ++i, ++t)
278 BOOST_TEST(lexical_cast<T>(to_str<CharT>(t)) == t);
279
280 // Test values around max:
281 t = max_val;
282 for(i = 0; i < counter; ++i, --t)
283 BOOST_TEST(lexical_cast<T>(to_str<CharT>(t)) == t);
284
285 // Test values around zero:
286 if(limits::is_signed)
287 for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
288 BOOST_TEST(lexical_cast<T>(to_str<CharT>(t)) == t);
289
290 // Test values around 100, 1000, 10000, ...
291 T ten_power = 100;
292 for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
293 {
294 // ten_power + 100 probably never overflows
295 for(t = ten_power - 100; t != ten_power + 100; ++t)
296 BOOST_TEST(lexical_cast<T>(to_str<CharT>(t)) == t);
297 }
298 }
299}
300
301template<class T>
302void test_conversion_from_to_integral_for_locale()
303{
304 std::locale current_locale;
305 typedef std::numpunct<char> numpunct;
306 numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
307 if ( !np.grouping().empty() )
308 {
309 BOOST_TEST_THROWS(
310 lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
311 , bad_lexical_cast);
312 BOOST_TEST_THROWS(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
313 BOOST_TEST_THROWS(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
314
315 // Exception must not be thrown, when we are using no separators at all
316 BOOST_TEST( lexical_cast<T>("30000") == static_cast<T>(30000) );
317 }
318
319
320 test_conversion_from_integral_to_integral<T>();
321
322 // This is a part of test_conversion_from_integral_to_string<T>('0') method,
323 // but with BOOST_TEST_EQ instead of BOOST_TEST. It is required to see
324 // what is produced by the to_str<char>(t) method in situations when result
325 // is different. BOOST_TEST does not work with wchar_t.
326 typedef std::numeric_limits<T> limits;
327 T t = (limits::min)();
328 BOOST_TEST_EQ(lexical_cast<std::string>(t), to_str<char>(t));
329
330 test_conversion_from_integral_to_string<T>('0');
331 test_conversion_from_string_to_integral<T>('0');
332#if !defined(BOOST_LCAST_NO_WCHAR_T)
333 if (lexical_cast<std::wstring>(t) != to_str<wchar_t>(t)) {
334 // Something went wrong, and now we are attempting to find and print the
335 // difference.
336 std::wstring wstr = to_str<wchar_t>(t);
337 std::string lcast_str = lexical_cast<std::string>(t);
338 std::string str;
339 str.reserve(res_arg: wstr.size());
340 for (std::size_t i = 0; i < wstr.size(); ++i) {
341 str.push_back(c: static_cast<char>(wstr[i]));
342 }
343
344 BOOST_TEST_EQ(lcast_str.length(), lexical_cast<std::wstring>(t).length());
345 BOOST_TEST_EQ(to_str<char>(t), str);
346 BOOST_TEST_EQ(lcast_str, str);
347 }
348
349 test_conversion_from_integral_to_string<T>(L'0');
350 test_conversion_from_string_to_integral<T>(L'0');
351#endif
352}
353
354struct restore_oldloc
355{
356 std::locale oldloc;
357 ~restore_oldloc() { std::locale::global(loc: oldloc); }
358};
359
360template<class T>
361void test_conversion_from_to_integral_minimal()
362{
363 char const zero = '0';
364 signed char const szero = '0';
365 unsigned char const uzero = '0';
366 test_conversion_from_integral_to_char<T>(zero);
367 test_conversion_from_char_to_integral<T>(zero);
368 test_conversion_from_integral_to_char<T>(szero);
369 test_conversion_from_char_to_integral<T>(szero);
370 test_conversion_from_integral_to_char<T>(uzero);
371 test_conversion_from_char_to_integral<T>(uzero);
372#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
373 wchar_t const wzero = L'0';
374 test_conversion_from_integral_to_char<T>(wzero);
375 test_conversion_from_char_to_integral<T>(wzero);
376#endif
377#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC)
378 char16_t const u16zero = u'0';
379 test_conversion_from_integral_to_char<T>(u16zero);
380 test_conversion_from_char_to_integral<T>(u16zero);
381#endif
382#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION) && !defined(BOOST_MSVC)
383 char32_t const u32zero = u'0';
384 test_conversion_from_integral_to_char<T>(u32zero);
385 test_conversion_from_char_to_integral<T>(u32zero);
386#endif
387
388 BOOST_TEST(lexical_cast<T>("-1") == static_cast<T>(-1));
389 BOOST_TEST(lexical_cast<T>("-9") == static_cast<T>(-9));
390 BOOST_TEST(lexical_cast<T>(-1) == static_cast<T>(-1));
391 BOOST_TEST(lexical_cast<T>(-9) == static_cast<T>(-9));
392
393 BOOST_TEST_THROWS(lexical_cast<T>("-1.0"), bad_lexical_cast);
394 BOOST_TEST_THROWS(lexical_cast<T>("-9.0"), bad_lexical_cast);
395 BOOST_TEST(lexical_cast<T>(-1.0) == static_cast<T>(-1));
396 BOOST_TEST(lexical_cast<T>(-9.0) == static_cast<T>(-9));
397
398 BOOST_TEST(lexical_cast<T>(static_cast<T>(1)) == static_cast<T>(1));
399 BOOST_TEST(lexical_cast<T>(static_cast<T>(9)) == static_cast<T>(9));
400 BOOST_TEST_THROWS(lexical_cast<T>(1.1f), bad_lexical_cast);
401 BOOST_TEST_THROWS(lexical_cast<T>(1.1), bad_lexical_cast);
402 BOOST_TEST_THROWS(lexical_cast<T>(1.1L), bad_lexical_cast);
403 BOOST_TEST_THROWS(lexical_cast<T>(1.0001f), bad_lexical_cast);
404 BOOST_TEST_THROWS(lexical_cast<T>(1.0001), bad_lexical_cast);
405 BOOST_TEST_THROWS(lexical_cast<T>(1.0001L), bad_lexical_cast);
406
407 BOOST_TEST(lexical_cast<T>("+1") == static_cast<T>(1) );
408 BOOST_TEST(lexical_cast<T>("+9") == static_cast<T>(9) );
409 BOOST_TEST(lexical_cast<T>("+10") == static_cast<T>(10) );
410 BOOST_TEST(lexical_cast<T>("+90") == static_cast<T>(90) );
411 BOOST_TEST_THROWS(lexical_cast<T>("++1"), bad_lexical_cast);
412 BOOST_TEST_THROWS(lexical_cast<T>("-+9"), bad_lexical_cast);
413 BOOST_TEST_THROWS(lexical_cast<T>("--1"), bad_lexical_cast);
414 BOOST_TEST_THROWS(lexical_cast<T>("+-9"), bad_lexical_cast);
415 // test_conversion_from_to_integral_for_locale
416
417 // Overflow test case from David W. Birdsall
418 std::string must_owerflow_str = (sizeof(T) < 16 ? "160000000000000000000" : "1600000000000000000000000000000000000000");
419 std::string must_owerflow_negative_str = (sizeof(T) < 16 ? "-160000000000000000000" : "-1600000000000000000000000000000000000000");
420 for (int i = 0; i < 15; ++i) {
421 BOOST_TEST_THROWS(lexical_cast<T>(must_owerflow_str), bad_lexical_cast);
422 BOOST_TEST_THROWS(lexical_cast<T>(must_owerflow_negative_str), bad_lexical_cast);
423
424 must_owerflow_str += '0';
425 must_owerflow_negative_str += '0';
426 }
427}
428
429template<class T>
430void test_conversion_from_to_integral()
431{
432 test_conversion_from_to_integral_minimal<T>();
433 typedef std::numpunct<char> numpunct;
434
435 restore_oldloc guard;
436 std::locale const& oldloc = guard.oldloc;
437
438 std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
439 std::string grouping2(grouping1);
440
441 test_conversion_from_to_integral_for_locale<T>();
442
443 try
444 {
445 std::locale newloc("");
446 std::locale::global(loc: newloc);
447
448 grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
449 }
450 catch(std::exception const& ex)
451 {
452 std::string msg("Failed to set system locale: ");
453 msg += ex.what();
454 std::cerr << msg;
455 }
456
457 if(grouping1 != grouping2)
458 test_conversion_from_to_integral_for_locale<T>();
459
460 if(grouping1.empty() && grouping2.empty())
461 std::cerr << "Formatting with thousands_sep has not been tested";
462}
463
464void test_conversion_from_to_short()
465{
466 test_conversion_from_to_integral<short>();
467}
468
469void test_conversion_from_to_ushort()
470{
471 test_conversion_from_to_integral<unsigned short>();
472}
473
474void test_conversion_from_to_int()
475{
476 test_conversion_from_to_integral<int>();
477}
478
479void test_conversion_from_to_uint()
480{
481 test_conversion_from_to_integral<unsigned int>();
482}
483
484void test_conversion_from_to_long()
485{
486 test_conversion_from_to_integral<long>();
487}
488
489void test_conversion_from_to_ulong()
490{
491 test_conversion_from_to_integral<unsigned long>();
492}
493
494void test_conversion_from_to_intmax_t()
495{
496 test_conversion_from_to_integral<boost::intmax_t>();
497}
498
499void test_conversion_from_to_uintmax_t()
500{
501 test_conversion_from_to_integral<boost::uintmax_t>();
502}
503
504#if defined(BOOST_HAS_LONG_LONG)
505
506void test_conversion_from_to_longlong()
507{
508 test_conversion_from_to_integral<boost::long_long_type>();
509}
510
511void test_conversion_from_to_ulonglong()
512{
513 test_conversion_from_to_integral<boost::ulong_long_type>();
514}
515
516#elif defined(BOOST_HAS_MS_INT64)
517
518void test_conversion_from_to_longlong()
519{
520 test_conversion_from_to_integral<__int64>();
521}
522
523void test_conversion_from_to_ulonglong()
524{
525 test_conversion_from_to_integral<unsigned __int64>();
526}
527
528#endif
529
530
531#ifdef BOOST_LCAST_TEST_128
532
533template <bool Specialized, class T>
534struct test_if_specialized {
535 static void test() {}
536};
537
538template <class T>
539struct test_if_specialized<true, T> {
540 static void test() {
541 test_conversion_from_to_integral_minimal<T>();
542 }
543};
544
545void test_conversion_from_to_int128()
546{
547 test_if_specialized<
548 std::numeric_limits<boost::int128_type>::is_specialized,
549 boost::int128_type
550 >::test();
551}
552
553void test_conversion_from_to_uint128()
554{
555 test_if_specialized<
556 std::numeric_limits<boost::int128_type>::is_specialized,
557 boost::uint128_type
558 >::test();
559}
560#endif
561
562template <typename SignedT>
563void test_integral_conversions_on_min_max_impl()
564{
565 typedef SignedT signed_t;
566 typedef typename boost::make_unsigned<signed_t>::type unsigned_t;
567
568 typedef std::numeric_limits<signed_t> s_limits;
569 typedef std::numeric_limits<unsigned_t> uns_limits;
570
571 BOOST_TEST_EQ(lexical_cast<unsigned_t>((uns_limits::max)()), (uns_limits::max)());
572 BOOST_TEST_EQ(lexical_cast<unsigned_t>((uns_limits::min)()), (uns_limits::min)());
573
574 BOOST_TEST_EQ(lexical_cast<signed_t>((s_limits::max)()), (s_limits::max)());
575 BOOST_TEST_EQ(lexical_cast<signed_t>((uns_limits::min)()), static_cast<signed_t>((uns_limits::min)()));
576
577 BOOST_TEST_EQ(lexical_cast<unsigned_t>((s_limits::max)()), static_cast<unsigned_t>((s_limits::max)()));
578 BOOST_TEST_EQ(lexical_cast<unsigned_t>((s_limits::min)()), static_cast<unsigned_t>((s_limits::min)()));
579}
580
581void test_integral_conversions_on_min_max()
582{
583 test_integral_conversions_on_min_max_impl<int>();
584 test_integral_conversions_on_min_max_impl<short>();
585
586#ifdef _MSC_VER
587 test_integral_conversions_on_min_max_impl<long int>();
588
589#if defined(BOOST_HAS_LONG_LONG)
590 test_integral_conversions_on_min_max_impl<boost::long_long_type>();
591#elif defined(BOOST_HAS_MS_INT64)
592 test_integral_conversions_on_min_max_impl<__int64>();
593#endif
594
595#ifdef BOOST_LCAST_TEST_128
596 test_integral_conversions_on_min_max_impl<boost::int128_type>();
597#endif
598#endif
599
600}
601
602void test_negative_integral() {
603 // From https://github.com/boostorg/lexical_cast/issues/45
604 BOOST_TEST_EQ(boost::lexical_cast<int>("-6575543"), -6575543);
605
606 BOOST_TEST_EQ(boost::lexical_cast<int>(-6575543), -6575543);
607
608 BOOST_TEST_EQ(boost::lexical_cast<int>("+6575543"), +6575543);
609 BOOST_TEST_EQ(boost::lexical_cast<int>(6575543), 6575543);
610
611 if (sizeof(short) == 2 && CHAR_BIT == 8) {
612 BOOST_TEST_EQ(boost::lexical_cast<short>("-32768"), -32768);
613 BOOST_TEST_EQ(boost::lexical_cast<short>(-32768), -32768);
614 BOOST_TEST_EQ(boost::lexical_cast<unsigned short>("-32768"), 32768);
615 BOOST_TEST_EQ(boost::lexical_cast<unsigned short>(-32768), 32768);
616
617 BOOST_TEST_EQ(boost::lexical_cast<unsigned short>(65535), 65535);
618
619 BOOST_TEST_THROWS(boost::lexical_cast<unsigned short>(-65536), bad_lexical_cast);
620 BOOST_TEST_EQ(boost::lexical_cast<unsigned short>(-65535), 1);
621 BOOST_TEST_EQ(boost::lexical_cast<unsigned short>(-65534), 2);
622
623 BOOST_TEST_THROWS(boost::lexical_cast<short>(65535), bad_lexical_cast);
624 BOOST_TEST_THROWS(boost::lexical_cast<short>(-65536), bad_lexical_cast);
625 BOOST_TEST_THROWS(boost::lexical_cast<short>(-65535), bad_lexical_cast);
626 }
627}
628
629int main()
630{
631 test_conversion_from_to_short();
632 test_conversion_from_to_ushort();
633 test_conversion_from_to_int();
634 test_conversion_from_to_uint();
635 test_conversion_from_to_long();
636 test_conversion_from_to_ulong();
637 test_conversion_from_to_intmax_t();
638 test_conversion_from_to_uintmax_t();
639#ifdef LCAST_TEST_LONGLONG
640 test_conversion_from_to_longlong();
641 test_conversion_from_to_ulonglong();
642#endif
643#ifdef BOOST_LCAST_TEST_128
644 test_conversion_from_to_int128();
645 test_conversion_from_to_uint128();
646#endif
647 test_integral_conversions_on_min_max();
648
649 test_negative_integral();
650
651 return boost::report_errors();
652}
653
654

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