diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 044354f..4878b32 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1338,15 +1338,39 @@ namespace boost return lcast_ret_float(output,start,finish); } -#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) private: - // we need workaround - bool no_long_double_80bit_realization_workaround(double& output, int) { - return convert_using_base_class(output); + // Not optimised converter + template + bool float_types_converter_internal(T& output, int /*tag*/) { + bool return_value = convert_using_base_class(output); + + /* Some compilers and libraries successfully + * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... + * We are trying to provide a unified behaviour, + * so we just forbid such conversions (as some + * of the most popular compilers/libraries do) + * */ + CharT const minus = lcast_char_constants::minus; + CharT const plus = lcast_char_constants::plus; + CharT const capital_e = lcast_char_constants::capital_e; + CharT const lowercase_e = lcast_char_constants::lowercase_e; + if ( return_value && + ( + output > (std::numeric_limits::max)() // +inf + || output < -(std::numeric_limits::max)() // -inf + || output != output // NaN + || *(finish-1) == lowercase_e // 1.0e + || *(finish-1) == capital_e // 1.0E + || *(finish-1) == minus // 1.0e- or 1.0E- + || *(finish-1) == plus // 1.0e+ or 1.0E+ + ) + ) return false; + + return return_value; } - // we do not need a workaround - bool no_long_double_80bit_realization_workaround(double& output,char) { + // Optimised converter + bool float_types_converter_internal(double& output,char /*tag*/) { return lcast_ret_float(output,start,finish); } public: @@ -1360,14 +1384,23 @@ namespace boost * double, because it will give a big precision loss. * */ boost::mpl::if_c< +#if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, +#else + 0 +#endif int, char - >::type dummy = 0; + >::type tag = 0; - return no_long_double_80bit_realization_workaround(output, dummy); + return float_types_converter_internal(output, tag); + } + + bool operator>>(long double& output) + { + int tag = 0; + return float_types_converter_internal(output, tag); } -#endif // Generic istream-based algorithm. // lcast_streambuf_for_target::value is true. diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 62449ea..afa16a6 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -921,17 +921,6 @@ void test_char_types_conversions() BOOST_CHECK(boost::lexical_cast(wc_arr) == std::wstring(wc_arr)); BOOST_CHECK(boost::lexical_cast(wc_arr[0]) == wc_arr[0]); - // Following tests depend on realization of std::locale. - // All we need to know, is that this functions must compile - BOOST_CHECK(boost::lexical_cast(c_arr[0]) == wc_arr[0]); - BOOST_CHECK(boost::lexical_cast(c_arr) == std::wstring(wc_arr)); - - BOOST_CHECK(boost::lexical_cast(sc_arr) != std::wstring(wc_arr) ); - BOOST_CHECK(boost::lexical_cast(uc_arr) != std::wstring(wc_arr) ); - - BOOST_CHECK_THROW(boost::lexical_cast(uc_arr[0]), bad_lexical_cast); - BOOST_CHECK_THROW(boost::lexical_cast(sc_arr[0]), bad_lexical_cast); - #endif }