forked from boostorg/conversion
Updates #5800 (partially fix lexical cast compilation with disabled exceptions)
[SVN r77116]
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
[version 1.0]
|
[version 1.0]
|
||||||
[copyright 2000-2005 Kevlin Henney]
|
[copyright 2000-2005 Kevlin Henney]
|
||||||
[copyright 2006-2010 Alexander Nasonov]
|
[copyright 2006-2010 Alexander Nasonov]
|
||||||
[copyright 2011 Antony Polukhin]
|
[copyright 2011-2012 Antony Polukhin]
|
||||||
[category String and text processing]
|
[category String and text processing]
|
||||||
[category Miscellaneous]
|
[category Miscellaneous]
|
||||||
[license
|
[license
|
||||||
@@ -170,6 +170,11 @@ limitation of compiler options that you use.
|
|||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section Changes]
|
[section Changes]
|
||||||
|
* [*boost 1.50.0 :]
|
||||||
|
|
||||||
|
* `boost::bad_lexical_cast` exception is now globaly visible and can be catched even if code is compiled with -fvisibility=hidden.
|
||||||
|
* Now it is possible to compile library with disabled exceptions.
|
||||||
|
|
||||||
* [*boost 1.49.0 :]
|
* [*boost 1.49.0 :]
|
||||||
|
|
||||||
* Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio).
|
* Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio).
|
||||||
|
@@ -104,7 +104,7 @@ _CRTIMP int __cdecl vswprintf(wchar_t * __restrict__ , const wchar_t * __restric
|
|||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
// exception used to indicate runtime lexical_cast failure
|
// exception used to indicate runtime lexical_cast failure
|
||||||
class bad_lexical_cast :
|
class BOOST_SYMBOL_VISIBLE bad_lexical_cast :
|
||||||
// workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
|
// workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
|
||||||
#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
|
#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
|
||||||
public std::exception
|
public std::exception
|
||||||
@@ -1958,52 +1958,52 @@ namespace boost
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class precision_loss_error : public boost::numeric::bad_numeric_cast
|
template<class Source, class Target >
|
||||||
|
struct detect_precision_loss
|
||||||
{
|
{
|
||||||
public:
|
typedef boost::numeric::Trunc<Source> Rounder;
|
||||||
virtual const char * what() const throw()
|
typedef Source source_type ;
|
||||||
{ return "bad numeric conversion: precision loss error"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class S >
|
typedef BOOST_DEDUCED_TYPENAME mpl::if_<
|
||||||
struct throw_on_precision_loss
|
is_arithmetic<Source>, Source, Source const&
|
||||||
{
|
>::type argument_type ;
|
||||||
typedef boost::numeric::Trunc<S> Rounder;
|
|
||||||
typedef S source_type ;
|
|
||||||
|
|
||||||
typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
|
|
||||||
|
|
||||||
static source_type nearbyint ( argument_type s )
|
static source_type nearbyint ( argument_type s )
|
||||||
{
|
{
|
||||||
source_type orig_div_round = s / Rounder::nearbyint(s);
|
const source_type orig_div_round = s / Rounder::nearbyint(s);
|
||||||
|
const source_type eps = std::numeric_limits<source_type>::epsilon();
|
||||||
|
|
||||||
|
if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps)
|
||||||
|
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
||||||
|
|
||||||
if ( (orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > std::numeric_limits<source_type>::epsilon() )
|
|
||||||
BOOST_THROW_EXCEPTION( precision_loss_error() );
|
|
||||||
return s ;
|
return s ;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef typename Rounder::round_style round_style;
|
typedef typename Rounder::round_style round_style;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
template<class Source, class Target >
|
||||||
|
struct nothrow_overflow_handler
|
||||||
|
{
|
||||||
|
void operator() ( boost::numeric::range_check_result r )
|
||||||
|
{
|
||||||
|
if (r != boost::numeric::cInRange)
|
||||||
|
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
template<typename Target, typename Source>
|
template<typename Target, typename Source>
|
||||||
struct lexical_cast_dynamic_num_not_ignoring_minus
|
struct lexical_cast_dynamic_num_not_ignoring_minus
|
||||||
{
|
{
|
||||||
static inline Target lexical_cast_impl(const Source &arg)
|
static inline Target lexical_cast_impl(const Source &arg)
|
||||||
{
|
{
|
||||||
try{
|
return boost::numeric::converter<
|
||||||
typedef boost::numeric::converter<
|
|
||||||
Target,
|
Target,
|
||||||
Source,
|
Source,
|
||||||
boost::numeric::conversion_traits<Target,Source>,
|
boost::numeric::conversion_traits<Target,Source>,
|
||||||
boost::numeric::def_overflow_handler,
|
nothrow_overflow_handler<Source, Target>,
|
||||||
throw_on_precision_loss<Source>
|
detect_precision_loss<Source, Target>
|
||||||
> Converter ;
|
>::convert(arg);
|
||||||
|
|
||||||
return Converter::convert(arg);
|
|
||||||
} catch( ::boost::numeric::bad_numeric_cast const& ) {
|
|
||||||
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
|
||||||
}
|
|
||||||
BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2012,25 +2012,17 @@ namespace boost
|
|||||||
{
|
{
|
||||||
static inline Target lexical_cast_impl(const Source &arg)
|
static inline Target lexical_cast_impl(const Source &arg)
|
||||||
{
|
{
|
||||||
try{
|
|
||||||
typedef boost::numeric::converter<
|
typedef boost::numeric::converter<
|
||||||
Target,
|
Target,
|
||||||
Source,
|
Source,
|
||||||
boost::numeric::conversion_traits<Target,Source>,
|
boost::numeric::conversion_traits<Target,Source>,
|
||||||
boost::numeric::def_overflow_handler,
|
nothrow_overflow_handler<Source, Target>,
|
||||||
throw_on_precision_loss<Source>
|
detect_precision_loss<Source, Target>
|
||||||
> Converter ;
|
> converter_t;
|
||||||
|
|
||||||
bool has_minus = ( arg < 0);
|
return (
|
||||||
if ( has_minus ) {
|
arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg)
|
||||||
return static_cast<Target>(-Converter::convert(-arg));
|
);
|
||||||
} else {
|
|
||||||
return Converter::convert(arg);
|
|
||||||
}
|
|
||||||
} catch( ::boost::numeric::bad_numeric_cast const& ) {
|
|
||||||
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
|
||||||
}
|
|
||||||
BOOST_UNREACHABLE_RETURN(static_cast<Target>(0));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -39,5 +39,8 @@ test-suite conversion
|
|||||||
[ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
|
[ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
|
||||||
[ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <toolset>msvc:<nowchar>on ]
|
[ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <toolset>msvc:<nowchar>on ]
|
||||||
[ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <define>BOOST_NO_STD_LOCALE ]
|
[ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <define>BOOST_NO_STD_LOCALE ]
|
||||||
|
[ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <define>BOOST_NO_EXCEPTIONS ]
|
||||||
;
|
;
|
||||||
|
#Add missing flags, when numeric_cast compilation with exceptions disabled will be fixed:
|
||||||
|
# [ run lexical_cast_no_exceptions_test.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <define>BOOST_NO_EXCEPTIONS <toolset>gcc:<cflags>-fno-exceptions ]
|
||||||
|
|
||||||
|
95
test/lexical_cast_no_exceptions_test.cpp
Executable file
95
test/lexical_cast_no_exceptions_test.cpp
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
// Unit test for boost::lexical_cast.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org for most recent version, including documentation.
|
||||||
|
//
|
||||||
|
// Copyright Antony Polukhin, 2012.
|
||||||
|
//
|
||||||
|
// 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 <boost/config.hpp>
|
||||||
|
|
||||||
|
#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 <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <boost/range/iterator_range.hpp>
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
#error "This test must be compiled with -DBOOST_NO_EXCEPTIONS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool g_was_exception = false;
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
void throw_exception(std::exception const & ) {
|
||||||
|
g_was_exception = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
|
||||||
|
|
||||||
|
struct Escape
|
||||||
|
{
|
||||||
|
Escape(){}
|
||||||
|
Escape(const std::string& s)
|
||||||
|
: str_(s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string str_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
|
||||||
|
{
|
||||||
|
return o << rhs.str_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::istream& operator>> (std::istream& i, Escape& rhs)
|
||||||
|
{
|
||||||
|
return i >> rhs.str_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_exceptions_off()
|
||||||
|
{
|
||||||
|
Escape v("");
|
||||||
|
|
||||||
|
g_was_exception = false;
|
||||||
|
lexical_cast<char>(v);
|
||||||
|
BOOST_CHECK(g_was_exception);
|
||||||
|
|
||||||
|
g_was_exception = false;
|
||||||
|
lexical_cast<unsigned char>(v);
|
||||||
|
BOOST_CHECK(g_was_exception);
|
||||||
|
|
||||||
|
v = lexical_cast<Escape>(100);
|
||||||
|
BOOST_CHECK_EQUAL(lexical_cast<int>(v), 100);
|
||||||
|
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(v), 100u);
|
||||||
|
|
||||||
|
v = lexical_cast<Escape>(0.0);
|
||||||
|
BOOST_CHECK_EQUAL(lexical_cast<double>(v), 0.0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(lexical_cast<short>(100), 100);
|
||||||
|
BOOST_CHECK_EQUAL(lexical_cast<float>(0.0), 0.0);
|
||||||
|
|
||||||
|
g_was_exception = false;
|
||||||
|
lexical_cast<short>(700000);
|
||||||
|
BOOST_CHECK(g_was_exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||||
|
{
|
||||||
|
unit_test::test_suite *suite =
|
||||||
|
BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_EXCEPTIONS");
|
||||||
|
suite->add(BOOST_TEST_CASE(&test_exceptions_off));
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user