Boost logo

Boost :

Subject: [boost] [safe numerics] comment
From: Robert Ramey (ramey_at_[hidden])
Date: 2017-03-08 17:36:56


I'm re-posting Vicente's message which apparently got lost in a server
issue so we can respond to it.

Robert Ramey

Hi,
let me start with some comments and questions.
I was wondering if the requirements of Numeric don't need some kind of
conversions between other numeric types.
https://htmlpreview.github.io/?https://raw.githubusercontent.com/robertramey/safe_numerics/master/doc/html/numeric.html

T(u)
T{u}
How can you implement the conversion from safe<U> to T if you can not
convert from U to T?

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.

Having implicit conversion in both directions is suspect.
Why the explicit conversion between safe<T> and safe<U> are not allowed
when T and U are not the same?

IMO, safe_base<T> is either not trivial default constructible and we
check the validity of 0, if we don't check it, we should declare it
=default.

The current definition doesn't adds nothing and makes the type a non-POD
and non trivial_default_constructible, which forbids its use on binary
messages.
      constexpr explicit safe_base() {
          // this permits creating of invalid instances. This is inline
          // with C++ built-in but violates the premises of the whole
library
          // choice are:
          // do nothing - violates premise of he library that all safe
objects
          // are valid
          // initialize to valid value - violates C++ behavior of types.
          // add "initialized" flag. Preserves fixes the above, but doubles
          // "overhead"
          // still pending on this.
      }
I'll suggest to use
      constexpr safe_base() = default;

BTW, why the default constructor is declared explicit?
As you say, could we talk of safe<short> when we can have one
uninitialized?

I believe this needs to appear clearly on the documentation if not
already in.

Has safe<const T> a sense?

Integer<T> are not traits as there is a compiler error when T is not an
integer :(

template <class T>
class Integer : public Numeric<T> {
      // integer types must have the corresponding numeric trait.
      static_assert(
          std::numeric_limits<T>::is_integer,
          "Fails to fulfill requirements for an integer type"
      );
};

The same for Numeric. Have you considered to define traits (usable with
SFINAE)?

I don't see a concept SafeNumeric. Have you considerd it?

BTW, these concept classes check only for a single requirement.
Shouldn't you specialize numeric_limits lowest()?

Have you considered to define basic algorithms managing with the valid
conversion between Numeric with the different policies, as Lawrence
Crowl is proposing for the standard?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0103r1.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0105r1.html

I find weird the way you are including the files
      #include "concept/integer.hpp"
      #include "concept/exception_policy.hpp"
      #include "concept/promotion_policy.hpp"
      #include "safe_common.hpp"
      #include "exception_policies.hpp"
      #include "boost/concept/assert.hpp"
I believed we used to inlcude boost files using <> and the absolute path.

Is this a good practice? Does it allows the compiler to perform better?

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk