lmi
[Top][All Lists]
Advanced

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

Re[2]: [lmi] passing objects instead of references to value_cast


From: Vadim Zeitlin
Subject: Re[2]: [lmi] passing objects instead of references to value_cast
Date: Sun, 22 Jun 2008 15:15:35 +0200
Date: Fri, 13 Jun 2008 03:54:37 +0200

On Mon, 02 Jun 2008 18:51:43 +0000 Greg Chicares <address@hidden> wrote:

GC> > or simply disable the test (perhaps for this compiler only)
GC> > and continue testing with Comeau and MSVC?
GC> 
GC> Yes, I think the best approach is to guard those particular
GC> tests with something like:
GC> 
GC>   #if !(defined __GNUC__ && 40199 <= LMI_GCC_VERSION < 40200)
GC>     ...cast-to-bool tests...
GC>   #endif //  !(defined __GNUC__ && 40199 <= LMI_GCC_VERSION < 40200)

 Hello again,

 Unfortunately testing with Comeau turned out to be more challenging than I
thought it would be. As I'd really like to finish with MSVC build I want to
submit the patch fixing the problem for it without testing it with Comeau
(but after testing it with g++ and, after finally fixing the remaining
problems with MSVC, with MSVC).

 Notice that I decided to use boost::is_arithmetic<> instead of continuing
to use std::numeric_limits<> after applying remove_const<> to FromDeref
type because the former seems more natural to me and because I thought that
"boost::remove_const<typename boost::remove_reference<From> >" was a bit
clumsy but if you prefer to keep using std::numeric_limits<> it can be done
too. The only difference between these 2 approaches is that
std::numeric_limits<> can be specialized for user-defined types while
boost::is_arithmetic<> is only true for the built-in types. However I
didn't find any specializations of std::numeric_limits<> in LMI code so the
point is moot.

 The rest of the patch, which follows, should be trivial enough to not
raise any questions but please let me know if you see anything wrong.

 Thanks in advance,
VZ

--- datum_string.hpp    2008-01-01 18:30:08 +0000
+++ datum_string.hpp    2008-06-02 09:49:07 +0000
@@ -61,14 +61,14 @@
 
 template<>
 inline datum_string value_cast<datum_string,std::string>
-    (std::string from)
+    (const std::string& from)
 {
     return datum_string(from);
 }
 
 template<>
 inline std::string value_cast<std::string,datum_string>
-    (datum_string from)
+    (const datum_string& from)
 {
     return from.value();
 }

--- value_cast.hpp      2008-01-01 18:30:08 +0000
+++ value_cast.hpp      2008-06-13 01:32:59 +0000
@@ -116,7 +116,7 @@
 ///   because casts go the other way."
 
 template<typename To, typename From>
-To value_cast(From from);
+To value_cast(From const& from);
 
 enum cast_method
     {e_both_numeric
@@ -157,7 +157,7 @@
 /// value-preserving relation.
 
 template<typename To, typename From>
-To numeric_value_cast(From from)
+To numeric_value_cast(From const& from)
 {
     To result = boost::numeric_cast<To>(from);
     if(result == from)
@@ -194,6 +194,8 @@
 template<typename To, typename From>
 struct value_cast_choice
 {
+    typedef typename boost::remove_reference<From>::type FromDeref;
+
     enum
         {
         // Here, is_convertible means 'From' is convertible to 'To'.
@@ -203,15 +205,15 @@
     enum
         {
         both_numeric =
-                std::numeric_limits<To  >::is_specialized
-            &&  std::numeric_limits<From>::is_specialized
+                boost::is_arithmetic<FromDeref>::value
+            &&  boost::is_arithmetic<To>::value
         };
 
     enum
         {
         one_numeric_one_string =
-                boost::is_arithmetic<From>::value && is_string<To  >::value
-            ||  boost::is_arithmetic<To  >::value && is_string<From>::value
+                boost::is_arithmetic<FromDeref>::value && is_string<To>::value
+            ||  boost::is_arithmetic<To>::value && is_string<FromDeref>::value
         };
 
     enum
@@ -235,39 +237,39 @@
 struct value_cast_chooser<To,From,e_both_numeric>
 {
     static cast_method method() {return e_both_numeric;}
-    To operator()(From from)    {return numeric_value_cast<To>(from);}
+    To operator()(From const& from)    {return numeric_value_cast<To>(from);}
 };
 
 template<typename To, typename From>
 struct value_cast_chooser<To,From,e_direct>
 {
     static cast_method method() {return e_direct;}
-    To operator()(From from)    {throw_if_null_pointer(from); return from;}
+    To operator()(From const& from)    {throw_if_null_pointer(from); return 
from;}
 };
 
 template<typename To, typename From>
 struct value_cast_chooser<To,From,e_numeric_io>
 {
     static cast_method method() {return e_numeric_io;}
-    To operator()(From from)    {return numeric_io_cast<To>(from);}
+    To operator()(From const& from)    {return numeric_io_cast<To>(from);}
 };
 
 template<typename To, typename From>
 struct value_cast_chooser<To,From,e_stream>
 {
     static cast_method method() {return e_stream;}
-    To operator()(From from)    {return stream_cast<To>(from);}
+    To operator()(From const& from)    {return stream_cast<To>(from);}
 };
 
 template<typename To, typename From>
-To value_cast(From from)
+To value_cast(From const& from)
 {
     BOOST_STATIC_ASSERT(!boost::is_pointer<To>::value);
     return value_cast_chooser<To,From>()(from);
 }
 
 template<typename To, typename From>
-To value_cast(From from, To)
+To value_cast(From const& from, To)
 {
     return value_cast<To,From>(from);
 }
@@ -280,7 +282,7 @@
 // with borland tools.
 
 template<typename To, typename From>
-To value_cast(From from, To = To())
+To value_cast(From const& from, To = To())
 {
     return stream_cast<To>(from);
 }

--- value_cast_test.cpp 2008-03-30 13:13:15 +0000
+++ value_cast_test.cpp 2008-06-13 01:25:36 +0000
@@ -718,7 +718,14 @@
     BOOST_TEST_EQUAL(true, value_cast<bool>(true));
     BOOST_TEST_EQUAL(false, value_cast<bool>(false));
 
+    // this test fails with mysterious compilation errors when using it with
+    // g++ 4.1.2 under amd64 (with both Boost 1.33 and 1.34), but passes with
+    // g++ 3.3, 3.4 and 4.2 on the same platform so it seems to be a compiler
+    // bug so we disable it for this particular compiler to avoid false test
+    // failures
+#if !defined(__GNUC__) || (LMI_GCC_VERSION < 40100) || (LMI_GCC_VERSION >= 
40200)
     BOOST_TEST_EQUAL(true, value_cast<bool>("1"));
+#endif
     // This fails; should it?
 //    BOOST_TEST_EQUAL(false, value_cast<bool>("0"));
 //    BOOST_TEST_THROW(value_cast<bool>(""), boost::bad_value_cast);







reply via email to

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