lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 83abe82 1/5: Replace numeric_value_cast()


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 83abe82 1/5: Replace numeric_value_cast()
Date: Sun, 23 Apr 2017 15:37:31 -0400 (EDT)

branch: master
commit 83abe8294dcf84799ed79203006484cfbb3f8c4e
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Replace numeric_value_cast()
    
    Expunged function template numeric_value_cast() was a cover function
    for boost::numeric_cast() that made the latter fulfill its contract to
    throw if it could not preserve value. Apparently that contract was a
    documentation error, and boost's actual intention was always to permit
    truncation when converting floating-point values to integers. The new
    bourn_cast, now used in place of numeric_value_cast(), enforces the
    no-truncation contract.
    
    Incidentally, included only appropriate headers, and improved
    documentation. Most notably, removed a suggestion that an exception
    such as bad_cast be used instead of std::runtime_error: that would
    decrease uniformity without offering any benefit, because lmi would
    not handle such an exception differently than any other.
---
 calendar_date.cpp   |  6 +++---
 value_cast.hpp      | 46 +++++-----------------------------------------
 value_cast_test.cpp | 39 +++++++++++++++++++++++++--------------
 3 files changed, 33 insertions(+), 58 deletions(-)

diff --git a/calendar_date.cpp b/calendar_date.cpp
index 2b95304..91a1450 100644
--- a/calendar_date.cpp
+++ b/calendar_date.cpp
@@ -25,7 +25,7 @@
 
 #include "alert.hpp"
 #include "assert_lmi.hpp"
-#include "value_cast.hpp"
+#include "bourn_cast.hpp"
 #include "zero.hpp"
 
 #include <algorithm>                    // std::max(), std::min()
@@ -691,7 +691,7 @@ class birthdate_limit
     double operator()(double candidate)
         {
         // Double parentheses circumvent the most vexing parse.
-        calendar_date z((jdn_t(numeric_value_cast<int>(candidate))));
+        calendar_date z((jdn_t(bourn_cast<int>(candidate))));
         return offset_ + notional_age(z, as_of_date_, alb_anb_) - limit_age_;
         }
 
@@ -705,7 +705,7 @@ class birthdate_limit
             ,*this
             );
         LMI_ASSERT(root_not_bracketed != z.second);
-        int j = numeric_value_cast<int>(z.first);
+        int j = bourn_cast<int>(z.first);
         j = std::min(j, as_of_date_.julian_day_number());
         j = std::max(j, a_priori_minimum_);
         j = std::min(j, a_priori_maximum_);
diff --git a/value_cast.hpp b/value_cast.hpp
index 210fb57..5c30e13 100644
--- a/value_cast.hpp
+++ b/value_cast.hpp
@@ -24,13 +24,12 @@
 
 #include "config.hpp"
 
+#include "bourn_cast.hpp"
 #include "numeric_io_cast.hpp"
 #include "stream_cast.hpp"
 
-#include <boost/cast.hpp>
-
-#include <sstream>
 #include <stdexcept>
+#include <string>
 #include <type_traits>
 
 // INELEGANT !! Test the runtime performance of value_cast() compared
@@ -45,13 +44,10 @@
 // template function value_cast for string-like types, as was done
 // for template class datum_string.
 
-// INELEGANT !! Exceptions thrown from numeric_io_cast and stream_cast
-// ought perhaps to be derived from std::bad_cast.
-
 /// Function template value_cast() converts between types, choosing a
 /// conversion method in the following order of decreasing preference:
-///   numeric_value_cast  for number <--> number
-///   direct conversion   for intraconvertible types not both numeric
+///   bourn_cast          for number <--> number
+///   direct conversion   for interconvertible types not both numeric
 ///   numeric_io_cast     for number <--> string
 ///   stream_cast         for all other cases
 ///
@@ -142,38 +138,6 @@ void throw_if_null_pointer(T* t)
         }
 }
 
-/// Function template numeric_value_cast() wraps boost::numeric_cast
-/// to make it DWISOTT according to the boost-1.31.0 documentation:
-///   "An exception is thrown when a runtime value-preservation
-///   check fails."
-/// The problem is that
-///   boost::numeric_cast<int>(2.71828);
-/// returns the integer 2 without throwing, but 2.71828 and 2 are
-/// different values. It seems unreasonable to call truncation a
-/// value-preserving relation.
-
-template<typename To, typename From>
-To numeric_value_cast(From const& from)
-{
-    To result = boost::numeric_cast<To>(from);
-    if(result == from)
-        {
-        return result;
-        }
-    else
-        {
-        std::ostringstream oss;
-        oss
-            << "Value not preserved converting "
-            << numeric_io_cast<std::string>(from)
-            << " to "
-            << numeric_io_cast<std::string>(result)
-            << " ."
-            ;
-        throw std::runtime_error(oss.str());
-        }
-}
-
 /// Class template value_cast_choice is an appurtenance of function
 /// template value_cast(); it selects the best conversion method.
 ///
@@ -238,7 +202,7 @@ template<typename To, typename From>
 struct value_cast_chooser<To,From,e_both_numeric>
 {
     static cast_method method()     {return e_both_numeric;}
-    To operator()(From const& from) {return numeric_value_cast<To>(from);}
+    To operator()(From const& from) {return bourn_cast<To>(from);}
 };
 
 template<typename To, typename From>
diff --git a/value_cast_test.cpp b/value_cast_test.cpp
index fbb5979..2d1619b 100644
--- a/value_cast_test.cpp
+++ b/value_cast_test.cpp
@@ -141,22 +141,17 @@ int test_main(int, char*[])
     // A good compiler should warn about this conversion.
 //    value_cast<unsigned int>(-1);
 
-    // The boost-1.31.0 documentation says:
-    //   "An exception is thrown when a runtime value-preservation
-    //   check fails."
-    // yet this does not throw, even in boost-1.33.1, whose new
-    // numeric_cast delegates to boost::numeric::converter:
-    i = boost::numeric_cast<int>(2.71828);
-    // but these do:
+    // Forbidden truncation.
+
     BOOST_TEST_THROW
         (i = value_cast<int>(d)
         ,std::runtime_error
-        ,"Value not preserved converting 2.71828 to 2 ."
+        ,lmi_test::what_regex("^Cast.*would not preserve value\\.$")
         );
     BOOST_TEST_THROW
-        (numeric_value_cast<int>(2.71828)
+        (bourn_cast<int>(2.71828)
         ,std::runtime_error
-        ,"Value not preserved converting 2.71828 to 2 ."
+        ,lmi_test::what_regex("^Cast.*would not preserve value\\.$")
         );
 
     // This conversion should work: value is exactly preserved.
@@ -724,9 +719,17 @@ int boost_tests()
 
     BOOST_TEST_EQUAL(1,value_cast<int>(1.0));
 
-    BOOST_TEST_THROW(value_cast<int>(1.23), std::runtime_error, "");
+    BOOST_TEST_THROW
+        (value_cast<int>(1.23)
+        ,std::runtime_error
+        ,lmi_test::what_regex("^Cast.*would not preserve value\\.$")
+        );
 
-    BOOST_TEST_THROW(value_cast<int>(1e20), boost::numeric::positive_overflow, 
"");
+    BOOST_TEST_THROW
+        (value_cast<int>(1e20)
+        ,std::runtime_error
+        ,"Cast would transgress upper limit."
+        );
     BOOST_TEST_EQUAL(1, value_cast<int>(true));
     BOOST_TEST_EQUAL(0, value_cast<int>(false));
     BOOST_TEST_EQUAL(123, value_cast<int>("123"));
@@ -792,10 +795,18 @@ int boost_tests()
     BOOST_TEST_EQUAL(true, value_cast<bool>('\1'));
     BOOST_TEST_EQUAL(false, value_cast<bool>('\0'));
 
-    BOOST_TEST_THROW(value_cast<bool>('A'), boost::numeric::positive_overflow, 
"");
+    BOOST_TEST_THROW
+        (value_cast<bool>('A')
+        ,std::runtime_error
+        ,"Cast would transgress upper limit."
+        );
     BOOST_TEST_EQUAL(true, value_cast<bool>(1));
     BOOST_TEST_EQUAL(false, value_cast<bool>(0));
-    BOOST_TEST_THROW(value_cast<bool>(123), boost::numeric::positive_overflow, 
"");
+    BOOST_TEST_THROW
+        (value_cast<bool>(123)
+        ,std::runtime_error
+        ,"Cast would transgress upper limit."
+        );
     BOOST_TEST_EQUAL(true, value_cast<bool>(1.0));
     BOOST_TEST_EQUAL(false, value_cast<bool>(0.0));
     BOOST_TEST_EQUAL(true, value_cast<bool>(true));



reply via email to

[Prev in Thread] Current Thread [Next in Thread]