Reputation: 16272
In order to have effectively compile-time-sized subranges views of compile-time-sized arrays.
I have been using this technique for a while and since I never got a warning or an error I thought it was OK.
std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]); // subrange {{2,3}}
assert(ee[0] == 2);
Until I found these comments https://stackoverflow.com/a/36046533/225186
I can make gcc
produce a warning with this
int aaa = 5;
double& eee = reinterpret_cast<double&>(aaa);
or this
std::array<int,3> aaaa = 5;
std::array<double,2>& eeee = reinterpret_cast<std::array<double,2>&>(aaaa);
...but not with the first block of code.
It seems that the aliasing rules are not enforced if the two references are not exactly in the same address?
Everybody seems to agree that this is at least UB. Would this be OK? Or is even worst?
int aa[3] = {1,2,3};
int* ee = new(&aa[1]) int[2];
It would be perfect if I could say int ee[2] = new(&aa[1]) int[2];
because the type of ee
will carry the new size and I can use subviews recursively.
Can I use std::basic_string_view<int>
for this?
At cppreference the only constraint is that int
has to be char
-like.
(Which I think it is.)
Upvotes: 1
Views: 97
Reputation: 93314
std::array<int,3> aa = {{1,2,3}};
std::array<int,2>& ee = reinterpret_cast<std::array<int,2>&>(aa[1]);
This definitely breaks strict aliasing rules, and an access to ee
is undefined behavior.
See cppreference/reinterpret_cast/type aliasing:
...but not with the first block of code.
If your compiler is not producing a warning, it doesn't mean that everything is OK - warnings are not mandated by the Standard. Compilers try to be as helpful as possible, but they will not detect all Standard violations.
Upvotes: 1