AMDG On 03/10/2017 09:29 PM, John McFarlane via Boost wrote:
On Fri, Mar 10, 2017 at 11:59 AM Robert Ramey via Boost < boost@lists.boost.org> wrote:
I'm all ears. One thing I do NOT see is saturate. I've seen it mentioned in several places - but I'm not convinced.
You mean you don't see the need for it? It comes up quite often as a strategy for dealing with overflow and a safe integer type seems like a good place to house it. Even it it isn't implemented now, a policy interface which allows users to implement it is going to give the library more users who use it to make their integers safe - surely the point of the exercise here.
It should be possible to handle saturation with the following extension: - If the ExceptionPolicy returns non-void, then the value it returns will be converted to the result type (the safe type, that is, not the stored type). This requires two additional pieces to work: - The ExceptionPolicy needs to distinguish between positive and negative overflow. - There need to be special values that can convert to the min and max values of safe_base. // Hypothetical saturate ExceptionPolicy: template<class T> struct min_value_t { constexpr T operator()() const { return std::numeric_limits<T>::min(); } }; template<class T> struct max_value_t { constexpr T operator()() const { return std::numeric_limits<T>::max(); } }; template<template<class> class F> struct special_value_t { template<class T, class = typename enable_if_c<is_safe<T>::value, void>::type> constexpr operator T() const { return F<T>()(); } }; constexpr const special_value_t<min_value_t> min_value; constexpr const special_value_t<max_value_t> max_value; struct saturate { static auto overflow_error(const char *) { return max_value; } // ... };
Note that I'm not a saint. I DO permit n to be uninitialized. I did this because it's so common and I want the library to be useful on legacy and embedded code. I've got a lot of reservations about this and could change my mind.
<snip>. And of the list of things that makes fundamental scalar types unsafe, indeterminate value of default-initialized instances ranks higher than either overflow or divide-by-zero in my experience.
Why not let the ExceptionPolicy decide? Just add an uninitialized_error(const char*) to ExceptionPolicy. Combined with my hypothetical extension above, this would also allow automatic zero-initialization. Incidentally, I'm not personally very concerned about indeterminate values, as valgrind works quite nicely for flushing out such problems and they're usually easy to fix. In Christ, Steven Watanabe