$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;
+}
+