boostorg / safe_numerics

Replacements to standard numeric types which throw exceptions on errors
Boost Software License 1.0
211 stars 43 forks source link

support pointers #54

Open Akrean opened 6 years ago

Akrean commented 6 years ago

adding a safe o to a char* p causes the compiler to generate a static_cast from an integer to a pointer, which is invalid c++

robertramey commented 6 years ago

I'm not getting this. Please submit a little better example.

Akrean commented 6 years ago

safe offset = 6; const char* ptr = "Hello World"; ptr += offset; //<- here the compiler tells me that a static_cast from an integer to a pointer is invalid c++

robertramey commented 6 years ago

Hmmmm - wouldn't the be a good thing? Isn't this in the spirit of the library to highlight/detect all operations which don't make arithmetic sense?

I would expect your example to fail above - thus requiring the user to do the following:

ptr += static_cast(offset);

which I don't see as necessarily a bad thing. And if I were to permit that, then presumably I would have to check that the result doesn't overflow. So implementation would look like:

static_cast(ptr) += offset;

which would detect an overflow, but would likely not compile either due the casting the left hand side.

All this raises interesting, non-trivial questions about what the library should actually do in certain cases. I've wrestled with a bunch of similar cases and feel OK about the decisions I made. But I have to say I'm astounded how such a simple idea ends up generating so many deep questions about what arithmetic should be in the context of fixed point numbers.

TL;DR; I think about this some more.

arvidn commented 6 years ago

as a side-note: the correct type for offset is ptrdiff_t, not size_t.

robertramey commented 6 years ago

and I presume that ptrdiff_t is an alias for some sort of integer type.

I've thought about it a little bit more and I've concluded that you're correct. If I want to make a safe integer type a drop-in replacement for an integer type, I'll have to address the operation of adding to a pointer. Unfortunately this is kind of a pain as it's one more "special" case. I'm not going to deal with it right now as I'm focused on getting safe numerics checked into the normal boost distribution and preparing for a safe_numerics presentation at CppCon.

Thanks for spotting this.

Robert Ramey

muggenhor commented 6 years ago

and I presume that ptrdiff_t is an alias for some sort of integer type.

yes, from [support.types.layout]:

  1. The type ptrdiff_t is an implementation-defined signed integer type that can hold the difference of two subscripts in an array object, as described in [expr.add].
  2. The type size_­t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object ([expr.sizeof]).
robertramey commented 6 years ago

re-reading these comments leaves me in a quandary. On one hand I want safe to be a drop-in replacement and on the other I want catch all "unsafe" operations. I don't see a way to resolved these two competing goals. Still I haven't give up hope. My exception/error policy does permit one some flexibility (loose vs strict) to handle such situations. I'll look in to this some more. But it's low priority as I've got higher priority things to deal with.