[Top][All Lists]

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

Re: [lmi] Is bourn_cast demonstrably correct?

From: Vadim Zeitlin
Subject: Re: [lmi] Is bourn_cast demonstrably correct?
Date: Tue, 21 Mar 2017 17:45:14 +0100

On Tue, 21 Mar 2017 16:07:07 +0000 Greg Chicares <address@hidden> wrote:

GC> We can either accept operations that lose precision, or throw.

 I realize that sometimes we do need the former, but I think they should
be very explicit and bourn_cast<> just isn't, i.e. I'd never expect it to

GC>     if(!to_traits::is_integer)
GC>         {
GC>         static_assert(to_traits::is_integer || to_traits::is_iec559, "");
GC>         // Here's where we'd test whether value is preserved.
GC>         return static_cast<To>(from);
GC>         }
GC> BTW...doesn't that static_assert look weird? If I instead write
GC>     if(!to_traits::is_integer)
GC>         {
GC> //      static_assert(to_traits::is_integer || to_traits::is_iec559, "");
GC>         static_assert(to_traits::is_iec559, "");
GC>         }
GC> then I get
GC> /opt/lmi/src/lmi/bourn_cast.hpp: In instantiation of 'To bourn_cast(From) \
GC>   [with To = long unsigned int; From = long int]':
GC> /opt/lmi/src/lmi/bourn_cast.hpp:94:9: error: static assertion failed: 
GC>          static_assert(to_traits::is_iec559, "");        
GC>          ^
GC> but I thought a block-level static_assert would apply only inside its
GC> block--and this block shouldn't be entered with "To = long unsigned int".

 No, it doesn't work like this in C++11, you would need to use the same
SFINAE tricks as usual and introduce a helper function which would be
defined differently depending on to_traits::is_integer value. It does work
like you'd expect with C++17 "if constexpr" and this is just another
example why it's so nice, even though it doesn't really change the language
expressiveness, i.e. we can do everything it does without it -- but in a
much uglier way.

GC> It compiles if I write the assertion with the redundant condition above.

 Yes, you'll have to do it like this for now.

GC> >  I'd prefer to turn it around and use bourn_cast<> for integers only and
GC> > have some round_cast<> for the floating point numbers if necessary (right
GC> > now it doesn't seem to be needed at all, however, unless I'm missing
GC> > something).
GC> Consider the calendar_date example recently discussed. A root-finding
GC> function gives us a JDN as a variable of type double that has been
GC> rounded to an exact integral value, and we want to convert that value
GC> to type int. We'd like to have a general-purpose routine to do that,
GC> which will throw if the JDN is outside [INT_MIN, INT_MAX] or if we
GC> somehow failed to round it correctly.

 Rereading this, I realize that my "for integers only" above was ambiguous
as it could have meant "restrict it to integer types at compile-time" or
"throw if it's passed a non-integer value, of whichever type, at run-time".
I meant the latter, sorry for being imprecise.

GC> And I do want lmi's value_cast to remain a Grand Unified Cast that makes
GC> everything interconvertible. Right now, it uses numeric_value_cast<>()
GC> for all arithmetic <-> arithmetic conversions; we'd need to design
GC> something to take its place if bourn_cast is restricted to integers.

 As long as value_cast<> doesn't need to truncate floating point values, I
see no problem with using bourn_cast<> in it.


reply via email to

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