Boost logo

Boost :

Subject: Re: [boost] [safe numerics] comment
From: Robert Ramey (ramey_at_[hidden])
Date: 2017-03-09 05:46:42

On 3/8/17 1:40 PM, Vicente J. Botet Escriba via Boost wrote:
> Le 08/03/2017 à 19:52, Robert Ramey via Boost a écrit :

>>> How can you implement the conversion from safe<U> to T if you can not
>>> convert from U to T?
>> I believe this would fail - probably with some totally confusing error
>> message. I think the best would be:
>> a) Improve implementation of Numeric and other concepts with
>> static_asserts.
>> b) Use these implementations to check types when used.

> I believe you should start by stating clearly the requirements. The
> conversion between Numerics is needed if you want to support conversion
> from safe<U> to T.

The short form is that converting from a safe numeric type to any other
type will work if the arithmetic values of both types are the same. By
the same token, converting any type to a safe numeric type will work if
the arithmetic value is preserved. Any other conversion will invoke
error at compile or runtime.

>>> We have implicit conversion from T to Safe and from Safe to T
>>> template<class T>
>>> constexpr /*explicit*/ safe_base(const T & t);
>>> template<
>>> class R,
>>> typename std::enable_if<
>>> !boost::numeric::is_safe<R>::value,
>>> int
>>>> ::type = 0
>>> constexpr operator R () const;
>>> constexpr operator Stored () const;
>>> I believed that the conversion from Safe to T needed to be explicit.

we disagree here.
>> I'm convinced of this.
LOL I said this - but my brain must have been asleep.

The concern is that implicit conversion would
>> break the value checking.

> I don't follow you here.

By value checking I mean verification that the resulting value is the
same as the original value.

>> But I don't see that as a concern as
>> value checking is implemented by overloading the binary assignment
>> operator and the casting operator. So
>> void f(short x){
>> ...
>> }
>> safe<long> l = 42;

> Here you have an implicit conversion int -> safe<long> and this is safe.

>> short i = l; // will be checked at runtime and be OK
> Here there is an implicit conversion int -> safe<long> -> short that is
> not safe.

yes it is. if l is greater than numeric_limits<short>::max() then an
error condition will be invoked. It may fail - but it can never
go undetected.

> I believe that for a safe class, this should be forbidden at compile
> time. If the user wants to do the conversion she must be explicit

This would break just about all existing programs. It would make the
folling code illegal

safe<int> i = 0

The intention of the library is to make current program safe. It is not
a new programming idiom

> short i = safe<short>(l);
> or
> short i(l);
> Think about how std::duration works. When we can loss information,
> implicit conversion are dangerous and should be avoided. This is what
> you are trying to fix with your library, isn't it?

Right - and I have. But implicit conversion is not the culprit. It's
unchecked conversion which causes problems.

>> f(l); // conversion to short will be checked at runtime and be OK
> I will expect an explicit conversion here.

again - we disagree.

>> l = 123412312321123;
>> i = l; // will throw at runtime
>> f(l); // will throw at runtime
> You say that you are convinced, but your conversions/constructors are
> implicit.
Hmmm- Right - I was mixed up.
>>> Having implicit conversion in both directions is suspect.

>>> Why the explicit conversion between safe<T> and safe<U> are not allowed

they are allowed. as are implicit conversions.

>> I believe they are. implicit conversions as well.
> Could you show how?

safe<short> i = 1024;
safe<char> j;
j = i; // invokes runtime error

i = j; // can never invoke error and no runtime checking is invoked.
>>> when T and U are not the same?
>> they are. as long as the arithmetic value doesn't change.
> What do you mean?

I think the above illustrates my point.

> Can you consider adding what the library supports in the documentation.

of course.

>> I didn't need them. What I did need and used is to create some traits
>> "is_safe" and maybe a couple of others - off hand I don't remember.

> Well, I believe that soon or later some one would need a traits that
> can be used using SFINAE.

certainly not now. I'm not sure it's there's a need or use for it. But
once concepts is available, it wouldn't be hard to upgrade the current
concept code to use concepts. Then the the concepts could be used as
traits for dispatch.

> I was looking fro it here and it is not
it's here - safe_numerics/include/concept/safe_numeric.hpp . It's based
on BCC. But I didn't use it in code.

>> safe numerics is much more practical for users to use. But it's also
>> much more complex to implement. I asked Bjarne at his presentation at
>> CPPCon 2016 about his view of Boost. His response included the
>> comment that he thought many boost library were overly complex. I
>> would certainly agree that many boost libraries are too complex to be
>> in something like a C++ standard. This is one of the main reasons I'm
>> pivoting toward boost and away from the inclusion in the standard.
> Well people have different needs. C/C++ integers are too dangerous and
> error prone. I'm sure a good safe integer library will find its users.

>>> I find weird the way you are including the files
>>> #include "concept/integer.hpp"

> Thanks, I have used to use <lib/file.hpp>, and considered "file.hpp" a
> bad style as I have seen a lot of "../..folder/file.h", but now that I
> think more on it there are also good uses of "file.hpp".
>> Thanks for your comments, they are always helpful and appreciated.
> I'm not sure I will have time to review your library in deep.
> Best,
> Vicente
>> Robert Ramey
>>> Best,
>>> Vicente
>>> _______________________________________________
>>> Unsubscribe & other changes:
>> _______________________________________________
>> Unsubscribe & other changes:
> _______________________________________________
> Unsubscribe & other changes:

Boost list run by bdawes at, gregod at, cpdaniel at, john at