Document #: | P3383R1 |
Date: | 2024-11-19 |
Project: | Programming Language C++ |
Audience: |
Library Evolution Working Group (LEWG) SG23 Safety and Security |
Reply-to: |
Stephan Lachnit <stephan.lachnit@cern.ch> Xavier Bonaventura (BMW) <xavier.bonaventura@bmw.de> |
This paper proposes element access with bounds checking to
std::mdspan
via at()
member functions.
Update wording to align with [P2821R5]:
__cpp_lib_mdspan
instead of
adding __cpp_lib_mdspan_at
at()
as
freestanding deleted and adjust freestanding comments of header and
classInitial version
The new
at()
member
functions provide memory-safe element access to
std::mdspan
,
and thus have defined behavior. Out-of-bound access can be caught by
catching the std::out_of_range
exception.
In [P2821R5], element access with bounds
checking via
at()
has
been added to
std::span
.
One of the main motivations for this change was consistency with other
containers that have element access with bounds checking via
at()
.
Similarly, such element access should be added to
std::mdspan
.
The impact of this proposal on the standard is low. The proposed
function signatures for the
at()
member
functions are identical to the function signatures for the subscript
operators as proposed in [P0009R18].
One consideration is that the
at()
method
has previously not been used with multi-dimensional arguments. However,
this was also true for the subscript operator before the possibility was
introduced in [P2128R6].
The wording is relative to [N4993].
In 17.3.2 ([version.syn]), adjust
the value of __cpp_lib_mdspan
to the
date of this proposal’s adoption.
In 23.7.3.2 ([mdspan.syn]), change the following lines:
- // all freestanding
+ // mostly freestanding
namespace std {
// 23.7.3.6, class template mdspan
template<class ElementType, class Extents, class LayoutPolicy = layout_right,
class AccessorPolicy = default_accessor<ElementType>>- class mdspan;
+ class mdspan; // partially freestanding
In 23.7.3.6.1 ([mdspan.mdspan.overview]), add the following immediately after the subscript operators:
template<class... OtherIndexTypes> constexpr reference at(OtherIndexTypes... indices) const; // freestanding-deleted template<class OtherIndexType> constexpr reference at(span<OtherIndexType, rank()> indices) const; // freestanding-deleted template<class OtherIndexType> constexpr reference at(const array<OtherIndexType, rank()>& indices) const; // freestanding-deleted
In 23.7.3.6.3 ([mdspan.mdspan.members]), add the following immediately after the subscript operators:
template<class... OtherIndexTypes> constexpr reference at(OtherIndexTypes... indices) const;
7 Constraints:
- (7.1)
(is_convertible_v<OtherIndexTypes, index_type> && ...)
istrue
,- (7.2)
(is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...)
istrue
, and- (7.3)
sizeof...(OtherIndexTypes) == rank()
istrue
.8 Returns:
(*this)[indices...]
9 Throws:
out_of_range
if
indices_v[i] >= extent(i) || indices_v[i] < 0
for anyindices_v[i]
invector<OtherIndexTypes>({indices...})
.template<class OtherIndexType> constexpr reference at(span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType> constexpr reference at(const array<OtherIndexType, rank()>& indices) const;
10 Constraints:
- (10.1)
is_convertible_v<const OtherIndexType&, index_type>
istrue
, and- (10.2)
is_nothrow_constructible_v<index_type, const OtherIndexType&>
istrue
.11 Returns:
(*this)[indices]
12 Throws:
out_of_range
if
indices[i] >= extent(i) || indices[i] < 0
for anyindices[i]
inindices
.
The at()
member functions have been implemented in the
std::mdspan
reference implementation from the Kokkos project at Sandia National
Laboratories [kokkos/mdspan], see [kokkos/mdspan#302].
at()
to
std::mdspan
.