Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77116 - in trunk: boost libs/conversion/doc libs/conversion/test
From: antoshkka_at_[hidden]
Date: 2012-02-25 11:58:47


Author: apolukhin
Date: 2012-02-25 11:58:46 EST (Sat, 25 Feb 2012)
New Revision: 77116
URL: http://svn.boost.org/trac/boost/changeset/77116

Log:
Updates #5800 (partially fix lexical cast compilation with disabled exceptions)
Added:
   trunk/libs/conversion/test/lexical_cast_no_exceptions_test.cpp (contents, props changed)
Text files modified:
   trunk/boost/lexical_cast.hpp | 90 ++++++++++++++++++---------------------
   trunk/libs/conversion/doc/lexical_cast.qbk | 7 ++
   trunk/libs/conversion/test/Jamfile.v2 | 5 +
   3 files changed, 51 insertions(+), 51 deletions(-)

Modified: trunk/boost/lexical_cast.hpp
==============================================================================
--- trunk/boost/lexical_cast.hpp (original)
+++ trunk/boost/lexical_cast.hpp 2012-02-25 11:58:46 EST (Sat, 25 Feb 2012)
@@ -104,7 +104,7 @@
 namespace boost
 {
     // 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
 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
         public std::exception
@@ -1958,52 +1958,52 @@
             }
         };
 
- class precision_loss_error : public boost::numeric::bad_numeric_cast
+ template<class Source, class Target >
+ struct detect_precision_loss
         {
- public:
- virtual const char * what() const throw()
- { return "bad numeric conversion: precision loss error"; }
- };
-
- template<class S >
- struct throw_on_precision_loss
- {
- typedef boost::numeric::Trunc<S> Rounder;
- typedef S source_type ;
+ typedef boost::numeric::Trunc<Source> Rounder;
+ typedef Source source_type ;
 
- typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
+ typedef BOOST_DEDUCED_TYPENAME mpl::if_<
+ is_arithmetic<Source>, Source, Source const&
+ >::type argument_type ;
 
          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 ;
          }
 
          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>
         struct lexical_cast_dynamic_num_not_ignoring_minus
         {
             static inline Target lexical_cast_impl(const Source &arg)
             {
- try{
- typedef boost::numeric::converter<
- Target,
- Source,
- boost::numeric::conversion_traits<Target,Source>,
- boost::numeric::def_overflow_handler,
- throw_on_precision_loss<Source>
- > Converter ;
-
- 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));
+ return boost::numeric::converter<
+ Target,
+ Source,
+ boost::numeric::conversion_traits<Target,Source>,
+ nothrow_overflow_handler<Source, Target>,
+ detect_precision_loss<Source, Target>
+ >::convert(arg);
             }
         };
 
@@ -2012,25 +2012,17 @@
         {
             static inline Target lexical_cast_impl(const Source &arg)
             {
- try{
- typedef boost::numeric::converter<
- Target,
- Source,
- boost::numeric::conversion_traits<Target,Source>,
- boost::numeric::def_overflow_handler,
- throw_on_precision_loss<Source>
- > Converter ;
-
- bool has_minus = ( arg < 0);
- if ( has_minus ) {
- 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));
+ typedef boost::numeric::converter<
+ Target,
+ Source,
+ boost::numeric::conversion_traits<Target,Source>,
+ nothrow_overflow_handler<Source, Target>,
+ detect_precision_loss<Source, Target>
+ > converter_t;
+
+ return (
+ arg < 0 ? -converter_t::convert(-arg) : converter_t::convert(arg)
+ );
             }
         };
 

Modified: trunk/libs/conversion/doc/lexical_cast.qbk
==============================================================================
--- trunk/libs/conversion/doc/lexical_cast.qbk (original)
+++ trunk/libs/conversion/doc/lexical_cast.qbk 2012-02-25 11:58:46 EST (Sat, 25 Feb 2012)
@@ -3,7 +3,7 @@
     [version 1.0]
     [copyright 2000-2005 Kevlin Henney]
     [copyright 2006-2010 Alexander Nasonov]
- [copyright 2011 Antony Polukhin]
+ [copyright 2011-2012 Antony Polukhin]
     [category String and text processing]
     [category Miscellaneous]
     [license
@@ -170,6 +170,11 @@
 [endsect]
 
 [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 :]
   
     * Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio).

Modified: trunk/libs/conversion/test/Jamfile.v2
==============================================================================
--- trunk/libs/conversion/test/Jamfile.v2 (original)
+++ trunk/libs/conversion/test/Jamfile.v2 2012-02-25 11:58:46 EST (Sat, 25 Feb 2012)
@@ -39,5 +39,8 @@
     [ 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_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 ]
+

Added: trunk/libs/conversion/test/lexical_cast_no_exceptions_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/conversion/test/lexical_cast_no_exceptions_test.cpp 2012-02-25 11:58:46 EST (Sat, 25 Feb 2012)
@@ -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;
+}
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk