From 8627f8bb8ac5dcc83b1a51d50fcd3078c098caed Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 14 Dec 2011 16:36:34 +0000 Subject: [PATCH] Fixes #6186 (treat conversions to/from single wchar_t character as conversions to/from unsigned short. Test added, documentation updated) [SVN r75937] --- doc/lexical_cast.qbk | 12 +++++ include/boost/lexical_cast.hpp | 28 +++++------ test/Jamfile.v2 | 1 + ...ical_cast_typedefed_wchar_test_runtime.cpp | 48 +++++++++++++++++++ 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100755 test/lexical_cast_typedefed_wchar_test_runtime.cpp 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 480d87a..5fa6a96 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -17,8 +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, Justin Viiret, Michael Hofmann -// 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 @@ -1093,8 +1093,6 @@ namespace boost namespace detail // optimized stream wrapper { - struct type_used_as_workaround_for_typedefed_wchar_ts{}; - // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Traits // usually char_traits @@ -1356,7 +1354,6 @@ namespace boost /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ private: - bool shr_unsigned(type_used_as_workaround_for_typedefed_wchar_ts /*var*/) {return true;} template bool shr_unsigned(Type& output) @@ -1484,15 +1481,8 @@ namespace boost } /************************************ OPERATORS >> ( ... ) ********************************/ - - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - ::boost::is_same::value - , type_used_as_workaround_for_typedefed_wchar_ts - , unsigned short - >::type ushort_ambiguity_workaround; - public: - bool operator>>(ushort_ambiguity_workaround& output){ return shr_unsigned(output); } + 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); } bool operator>>(short& output) { return shr_signed(output); } @@ -1504,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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 96ce8f6..8718301 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -36,5 +36,6 @@ test-suite conversion [ 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_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; +}