diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d7d9052..fdc5898 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -55,7 +55,13 @@ namespace boost { // exception used to indicate runtime lexical_cast failure - class bad_lexical_cast : public std::bad_cast + class bad_lexical_cast : + // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 +#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS + public std::exception +#else + public std::bad_cast +#endif #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 ) // under bcc32 5.5.1 bad_cast doesn't derive from exception @@ -521,11 +527,10 @@ namespace boost std::string::size_type const grouping_size = grouping.size(); CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; std::string::size_type group = 0; // current group number - char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0]; - // a) Since grouping is const, grouping[grouping.size()] returns 0. - // b) It's safe to assume here and below that CHAR_MAX - // is equivalent to unlimited grouping: + char last_grp_size = + grouping_size == 0 || grouping[0] <= 0 ? CHAR_MAX : grouping[0]; #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // Check that ulimited group is unreachable: BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif @@ -1120,6 +1125,7 @@ namespace boost # pragma warning( push ) # pragma warning( disable : 4701 ) // possible use of ... before initialization # pragma warning( disable : 4702 ) // unreachable code +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int' #endif template< typename Target @@ -1149,7 +1155,7 @@ namespace boost Target result; if(!(interpreter << arg && interpreter >> result)) - BOOST_LCAST_THROW_BAD_CAST(Source, Target); + BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; } #if (defined _MSC_VER) @@ -1191,11 +1197,7 @@ namespace boost Target result; if(!(interpreter << arg && interpreter >> result)) -#ifndef BOOST_NO_TYPEID - throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); -#else - throw_exception(bad_lexical_cast()); -#endif + BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; } diff --git a/lexical_cast.htm b/lexical_cast.htm index c9d37be..5457a33 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -194,32 +194,74 @@ public: Exception used to indicate runtime lexical_cast failure. -
-

Frequently Asked Questions

-

Q: Why does lexical_cast<int8_t>("127") throw bad_lexical_cast? -
A: The type int8_t is a typedef to char or signed char. +


+ + + +

Frequently Asked Questions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Question:Why does lexical_cast<int8_t>("127") throw bad_lexical_cast?
Answer:The type int8_t is a typedef to char or signed char. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown. -

Please use other integer types such as int or short int. If bounds checking + Please use other integer types such as int or short int. If bounds checking is important, you can also call numeric_cast: -

numeric_cast<int8_t>(lexical_cast<int>("127"));
+
Question:What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect?
Answer:As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: +
lexical_cast<std::string>(static_cast<int>(n));
+
Question:The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag?
Answer:May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. +
Question:Why std::cout << boost::lexical_cast<unsigned int>("-1"); does not throw, but outputs 4294967295?
Answer:boost::lexical_cast has the behavior of stringstream, which uses num_get functions of std::locale to convert numbers. If we look at the [22.2.2.1.2] of Programming languages — C++, we'll see, that num_get uses 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. +
-

Q: What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect? -
A: As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: - -

lexical_cast<std::string>(static_cast<int>(n));
- -

Q: The implementation always resets the ios_base::skipws flag of an underlying stream object. It breaks my operator>> that works only in presence of this flag. Can you remove code that resets the flag? -
A: May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver. - -

References

+

References

Changes

@@ -265,6 +307,12 @@ public:


-
© Copyright Kevlin Henney, 2000–2005
+
Copyright © Kevlin Henney, 2000-2005
+
Copyright © Alexander Nasonov, 2006-2010
+
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) +
diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 12e9deb..a994d13 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -11,6 +11,13 @@ // // Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it. +// +// We need this #define before any #includes: otherwise msvc will emit warnings +// deep within std::string, resulting from our (perfectly legal) use of basic_string +// with a custom traits class: +// +#define _SCL_SECURE_NO_WARNINGS + #include #if defined(__INTEL_COMPILER)