On Tue, 12 Mar 2019 at 14:15, Myriachan <
myri...@gmail.com> wrote:
>
> Right now, static_cast is prohibited between T(&)[] and T (&)[N]. This seems like an unnecessary restriction.
See
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0388r3.html
for a paper working its way through CWG. That permits, among other
things, implicit conversions that drop an array bound and static_casts
that add one back.
> Also, if you have a T (&)[N] that actually refers to a T (&)[M] where M > N, it's still undefined behavior to use that reference. Similarly, dereferencing a T (&)[1] referring to a T is also undefined behavior.
Those cases (where you don't actually have an array object of the
specified bound) are unaffected by P0388R3.
> So here are some of my proposed ideas:
>
> 1. Allow T (&)[N] to implicitly convert to T (&)[], and T (*)[N] to T (*)[]. This then automatically makes the opposite direction doable with static_cast.
(Will be done by P0388.)
> 2. Dereferencing a pointer/reference to an array is legal if at least N objects of type T exist there, and the indexed value X is less than N. Note that this rule would allow compilers to assume that at least N elements exist because that is the type.
We need to be careful to keep this case undefined:
struct A {
char x[3];
char y[4];
} a;
char (&r)[7] = static_cast<char(&)[7]>(a.x);
char q = r[5];
... since catching these kinds of things with sanitizers and the like
shows promise of being an important security hardening technique, and
giving that defined behavior would prevent a conforming compiler from
mitigating certain classes of buffer overflow bugs.
However, allowing array slicing (forming a reference to a subset of
the elements of a larger array) seems reasonable.
> Conversion between T * and T (*)[] or T (*)[N] would then be legal to use following a reinterpret_cast. I suppose that static_cast could support that as well, but that seems more dangerous to support.
>
>
> A potential downside here is an ABI break: template classes that handle unsized array references differently from sized array references would break. Similarly, some existing code might become ill-formed due to overload ambiguity or SFINAE differences.
Those kinds of things are a risk for any language change.