Reputation: 30128
Following code does not compile:
void fn(std::span<int> ) {}
int main() {
int arr[4][5]{};
fn(arr[0]);
std::mdspan msp(arr);
}
This is because std::mdspan is not constructible from a 2D C array. From what I see, this behavior was intentionally designed, as the deduction guide specifies the following:
requires(std::is_array_v<CArray> && std::rank_v<CArray> == 1)
However, I find this somewhat counterintuitive. Sometimes, I have a specific-size 2D array and would like to pass it to a generic function that operates on any 2D mdspan. It seems natural to me that this should be supported.
Upvotes: 1
Views: 62
Reputation: 96791
I had a quick look at the proposal but didn't find anything. My best guess is that N-dimensional arrays in C/C++ are just inherently ugly.
Let's say you have a flat int arr[4*5];
. You can construct a 2D span from pointer &arr[0]
(aka just arr
) and two dimensions.
Now if you try create the same 2D span from int arr[4][5];
, what pointer do you pass and store?
If you pass &arr[0][0]
(aka arr[0]
), you can only legally access arr[0][i]
and not the rest of arr[j][i]
.
While I doubt compilers will choke on this at runtime, I believe they do validate this in constexpr
contexts.
Passing &arr[0]
(aka just arr
) fixes that, but that's a different pointer type.
std::mdspan
is flexible enough to allow customizing which pointer type is stored (via a custom accessor), so do we cook up a custom accessor for N-dim arrays?
While I think it could be possible, accessors operate on 1D indices, so you would need to convert them back to N-dim indices to index the pointer, and so on.
A better solution would be to fix the language so that &arr[0][0]
can be used to access the entire arr[j][i]
, since people are doing this all the time anyway, and then the support can be added to std::mdspan
without the accessor nonsense.
Upvotes: 0