https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99471
Bug ID: 99471
Summary: Allow conversion from array of unknown bound to actual
known bound
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: wjwray at gmail dot com
Target Milestone: ---
P0388 "Permit conversions to arrays of unknown bound" in C++20
does not explicitly discuss conversion back from unknown bound
to the actual bound of the referenced object.
Discussion with Richard Smith suggests that it is (or should be)
allowed to static_cast back to the known bound:
int a[4]{1,2,3,4};
int (&r)[] = a; // P0388 conversion
int (&b)[4] = r; // error: cannot bind reference of type
// 'int (&)[4]' to 'int []'
It is intended that this be allowed (c.f. also bug 93191 end discussion).
However, it requires the compiler to trace the reference back to its object.
Allowing this enables new non-templated array-accepting function apis:
https://godbolt.org/z/1x4Tzs
constexpr // marking constexpr gives better codegen
int sum(int(&x)[]) // despite being not constant evaluated
{
auto& in = (int(&)[__builtin_object_size(x,0) / sizeof(int)])x;
int acc = 0;
for (int i : in)
acc += i;
return acc;
}
int main() {
int a[]{1,2,3,4};
return sum(a); // returns 10 (1+2+3+4)
}
Here, __builtin_object_size requires optimization flags of -O1 or greater
in order to chase back the referenced object and extract its size in bytes.
However, it is not constant evaluated so the C-style cast is casting to VLA.
If the size can indeed be extracted as an integral constant expression then
the cast is a static_cast, or implicit conversion, as above.
So, this 'bug' is two requests:
1. Allow static_cast from T(&)[] -> T(&)[N] where N is the actual size
(or pointer T(*)[] -> T(*)[N])
2. Provide a constant-evaluated builtin to extract the referenced object size
(strengthen __builtin_object_size if possible)
(Some sort of array_size builtin, as discussed for C, would be good here too.)