diff --git a/doc/lexical_cast.qbk b/doc/lexical_cast.qbk index b540267..0532b56 100644 --- a/doc/lexical_cast.qbk +++ b/doc/lexical_cast.qbk @@ -159,9 +159,21 @@ Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. +[pre +] + +* [*Question:] Why `boost::lexical_cast(L'A');` outputs 65 and `boost::lexical_cast(L"65");` does not throw? + * [*Answer:] If you are using an old version of Visual Studio or compile code with /Zc:wchar_t- flag, +`boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a +limitation of compiler options that you use. + [endsect] [section Changes] +* [*boost 1.49.0 :] + + * Added code to work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio). + * [*boost 1.48.0 :] * Added code to work with Inf and NaN on any platform. diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 0004461..5fa6a96 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,7 +17,8 @@ // enhanced with contributions from Terje Slettebo, // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin and other Boosters +// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, +// Cheng Yang and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 #include @@ -46,8 +47,10 @@ #include #include #include -#include - +#include +#ifndef BOOST_NO_CWCHAR +# include +#endif #ifndef BOOST_NO_STD_LOCALE # include @@ -145,6 +148,12 @@ namespace boost { typedef CharT type; }; + + template + struct stream_char< ::boost::container::basic_string > + { + typedef CharT type; + }; #endif #ifndef BOOST_LCAST_NO_WCHAR_T @@ -259,6 +268,24 @@ namespace boost typedef Traits type; }; + template + struct deduce_char_traits< CharT + , ::boost::container::basic_string + , Source + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , Target + , ::boost::container::basic_string + > + { + typedef Traits type; + }; + template struct deduce_char_traits< CharT , std::basic_string @@ -267,6 +294,15 @@ namespace boost { typedef Traits type; }; + + template + struct deduce_char_traits< CharT + , ::boost::container::basic_string + , ::boost::container::basic_string + > + { + typedef Traits type; + }; #endif } @@ -648,8 +684,8 @@ namespace boost , const CharT opening_brace, const CharT closing_brace) { using namespace std; - const wchar_t minus = lcast_char_constants::minus; - const wchar_t plus = lcast_char_constants::plus; + const CharT minus = lcast_char_constants::minus; + const CharT plus = lcast_char_constants::plus; const int inifinity_size = 8; bool has_minus = false; @@ -1257,6 +1293,14 @@ namespace boost return true; } + template + bool operator<<(::boost::container::basic_string const& str) + { + start = const_cast(str.data()); + finish = start + str.length(); + return true; + } + bool operator<<(bool value) { CharT const czero = lcast_char_constants::zero; @@ -1310,6 +1354,7 @@ namespace boost /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: + template bool shr_unsigned(Type& output) { @@ -1436,7 +1481,7 @@ namespace boost } /************************************ OPERATORS >> ( ... ) ********************************/ - public: + public: bool operator>>(unsigned short& output) { return shr_unsigned(output); } bool operator>>(unsigned int& output) { return shr_unsigned(output); } bool operator>>(unsigned long int& output) { return shr_unsigned(output); } @@ -1449,11 +1494,19 @@ namespace boost #elif defined(BOOST_HAS_MS_INT64) bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } bool operator>>(__int64& output) { return shr_signed(output); } - #endif - bool operator>>(CharT& output) { return shr_xchar(output); } + bool operator>>(char& output) { return shr_xchar(output); } bool operator>>(unsigned char& output) { return shr_xchar(output); } bool operator>>(signed char& output) { return shr_xchar(output); } +#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + bool operator>>(wchar_t& output) { return shr_xchar(output); } +#endif +#ifndef BOOST_NO_CHAR16_T + bool operator>>(char16_t& output) { return shr_xchar(output); } +#endif +#ifndef BOOST_NO_CHAR32_T + bool operator>>(char32_t& output) { return shr_xchar(output); } +#endif #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION bool operator>>(std::string& str) { str.assign(start, finish); return true; } # ifndef BOOST_LCAST_NO_WCHAR_T @@ -1462,6 +1515,9 @@ namespace boost #else template bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } + + template + bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } #endif /* * case "-0" || "0" || "+0" : output = false; return true; @@ -1598,6 +1654,12 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; + template + struct is_stdstring< ::boost::container::basic_string > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + template struct is_char_or_wchar { @@ -1698,6 +1760,18 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = true ); }; + template + struct is_char_array_to_stdstring< ::boost::container::basic_string, CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + + template + struct is_char_array_to_stdstring< ::boost::container::basic_string, const CharT* > + { + BOOST_STATIC_CONSTANT(bool, value = true ); + }; + #if (defined _MSC_VER) # pragma warning( push ) # pragma warning( disable : 4701 ) // possible use of ... before initialization diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 6820612..faeaa93 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -110,7 +110,7 @@ void test_char32_conversions(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(test_conversion_to_char)); suite->add(BOOST_TEST_CASE(test_conversion_to_int)); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 55aacc5..8718301 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,7 +14,12 @@ # bring in rules for testing import testing ; +import feature ; +feature.feature nowchar : on : + composite optional propagated link-incompatible ; +feature.compose on : /Zc:wchar_t- ; + test-suite conversion : [ run implicit_cast.cpp ] [ compile-fail implicit_cast_fail.cpp ] @@ -28,7 +33,9 @@ test-suite conversion [ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/static ] + [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] + [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] ; - diff --git a/test/lexical_cast_abstract_test.cpp b/test/lexical_cast_abstract_test.cpp index 4b92e49..70cdeca 100644 --- a/test/lexical_cast_abstract_test.cpp +++ b/test/lexical_cast_abstract_test.cpp @@ -28,7 +28,7 @@ void test_abstract(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_abstract)); diff --git a/test/lexical_cast_containers_test.cpp b/test/lexical_cast_containers_test.cpp new file mode 100644 index 0000000..5f98ac8 --- /dev/null +++ b/test/lexical_cast_containers_test.cpp @@ -0,0 +1,38 @@ +// Testing boost::lexical_cast with boost::container::string. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). + +#include +#include +#include + +void testing_boost_containers_basic_string(); + +using namespace boost; + +boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::container::string"); + suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string)); + + return suite; +} + +void testing_boost_containers_basic_string() +{ + BOOST_CHECK("100" == lexical_cast("100")); + BOOST_CHECK(L"100" == lexical_cast(L"100")); + + BOOST_CHECK("100" == lexical_cast(100)); + boost::container::string str("1000"); + BOOST_CHECK(1000 == lexical_cast(str)); +} + + diff --git a/test/lexical_cast_empty_input_test.cpp b/test/lexical_cast_empty_input_test.cpp index f655acd..42e7cec 100755 --- a/test/lexical_cast_empty_input_test.cpp +++ b/test/lexical_cast_empty_input_test.cpp @@ -49,7 +49,7 @@ void test_empty_string() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast. Empty input unit test"); suite->add(BOOST_TEST_CASE(&test_empty_iterator_range)); suite->add(BOOST_TEST_CASE(&test_empty_string)); diff --git a/test/lexical_cast_float_types_test.cpp b/test/lexical_cast_float_types_test.cpp index 72279bb..808f456 100755 --- a/test/lexical_cast_float_types_test.cpp +++ b/test/lexical_cast_float_types_test.cpp @@ -31,7 +31,7 @@ using namespace boost; unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast float types unit test"); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float)); suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double)); diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index 4617d5e..bb4331a 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -170,7 +170,7 @@ void test_inf_nan_long_double() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast inf anf nan parsing unit test"); suite->add(BOOST_TEST_CASE(&test_inf_nan_float)); suite->add(BOOST_TEST_CASE(&test_inf_nan_double)); diff --git a/test/lexical_cast_loopback_test.cpp b/test/lexical_cast_loopback_test.cpp index 5787996..25b18ec 100644 --- a/test/lexical_cast_loopback_test.cpp +++ b/test/lexical_cast_loopback_test.cpp @@ -30,7 +30,7 @@ void test_round_conversion_long_double(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_round_conversion_float)); suite->add(BOOST_TEST_CASE(&test_round_conversion_double)); diff --git a/test/lexical_cast_noncopyable_test.cpp b/test/lexical_cast_noncopyable_test.cpp index 6284b14..1f120d9 100644 --- a/test/lexical_cast_noncopyable_test.cpp +++ b/test/lexical_cast_noncopyable_test.cpp @@ -28,7 +28,7 @@ void test_noncopyable(); unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast unit test"); suite->add(BOOST_TEST_CASE(&test_noncopyable)); diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp new file mode 100755 index 0000000..752c3e5 --- /dev/null +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -0,0 +1,25 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). + +#include + +#include +#include + +int main() +{ +#ifdef BOOST_MSVC + BOOST_STATIC_ASSERT((boost::is_same::value)); +#endif + + return ::boost::lexical_cast(L"1000") == 1000; +} + + diff --git a/test/lexical_cast_typedefed_wchar_test_runtime.cpp b/test/lexical_cast_typedefed_wchar_test_runtime.cpp new file mode 100755 index 0000000..d01700a --- /dev/null +++ b/test/lexical_cast_typedefed_wchar_test_runtime.cpp @@ -0,0 +1,48 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2011. +// +// Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). + +#include + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include + +#include +using namespace boost; + +void test_typedefed_wchar_t_runtime() +{ +#ifndef BOOST_LCAST_NO_WCHAR_T +#ifdef BOOST_MSVC + BOOST_STATIC_ASSERT((boost::is_same::value)); + + + BOOST_CHECK_EQUAL(boost::lexical_cast(L'A'), 65); + BOOST_CHECK_EQUAL(boost::lexical_cast(L'B'), 66); + + BOOST_CHECK_EQUAL(boost::lexical_cast(L"65"), 65); + BOOST_CHECK_EQUAL(boost::lexical_cast(L"66"), 66); +#endif +#endif + BOOST_CHECK(1); +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast typedefed wchar_t runtime test"); + suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t_runtime)); + + return suite; +} diff --git a/test/lexical_cast_vc8_bug_test.cpp b/test/lexical_cast_vc8_bug_test.cpp index 151e4f8..9e5ef0b 100644 --- a/test/lexical_cast_vc8_bug_test.cpp +++ b/test/lexical_cast_vc8_bug_test.cpp @@ -60,7 +60,7 @@ void test_vc8_bug() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast vc8 bug unit test"); suite->add(BOOST_TEST_CASE(test_vc8_bug)); return suite; diff --git a/test/lexical_cast_wchars_test.cpp b/test/lexical_cast_wchars_test.cpp index 14ac461..acd78b1 100755 --- a/test/lexical_cast_wchars_test.cpp +++ b/test/lexical_cast_wchars_test.cpp @@ -48,7 +48,7 @@ void test_char_types_conversions() unit_test::test_suite *init_unit_test_suite(int, char *[]) { - unit_test_framework::test_suite *suite = + unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast char<->wchar_t unit test"); suite->add(BOOST_TEST_CASE(&test_char_types_conversions));