mdspan.at()

Document #: P3383R2
Date: 2025-02-22
Project: Programming Language C++
Audience: Library Working Group (LWG)
Reply-to: Stephan Lachnit
<>
Xavier Bonaventura (BMW)
<>

1 Introduction

This paper proposes element access with bounds checking to std::mdspan via at() member functions.

2 Revision history

2.1 R2

2.2 R1

Update wording to align with [P2821R5]:

2.3 R0

Initial version

3 Motivation

3.1 Safety

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.

3.2 Consistency

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.

4 Impact On the Standard

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].

5 Wording

The wording is relative to [N5001].

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> && ...) is true,
  • (7.2) (is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) is true, and
  • (7.3) sizeof...(OtherIndexTypes) == rank() is true.

8 Returns: (*this)[indices...].

9 Let I be extents_type::index_cast(std::move(indices)).

10 Throws: out_of_range if I is not a multidimensional index in extents().

template<class OtherIndexType>
  constexpr reference at(span<OtherIndexType, rank()> indices) const;
template<class OtherIndexType>
  constexpr reference at(const array<OtherIndexType, rank()>& indices) const;

11 Constraints:

  • (11.1) is_convertible_v<const OtherIndexType&, index_type> is true, and
  • (11.2) is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.

12 Effects: Let P be a parameter pack such that is_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true. Equivalent to: return at(extents_type::index-cast(as_const(indices[P]))...);

6 Feature Test Macro

LEWG decided to drop the bump of the feature test macro.

6.1 Poll

Remove the feature test macro bump from P3383R1

SF
F
N
A
SA
4 4 4 2 0

7 Reference Implementation

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].

8 References

[kokkos/mdspan] Reference implementation of mdspan.
https://github.com/kokkos/mdspan
[kokkos/mdspan#302] Add element access via at() to std::mdspan.
https://github.com/kokkos/mdspan/pull/302
[N5001] Thomas Köppe. 2024-12-17. Working Draft, Programming Languages — C++.
https://wg21.link/n5001
[P0009R18] Christian Trott, D.S. Hollman, Damien Lebrun-Grandie, Mark Hoemmen, Daniel Sunderland, H. Carter Edwards, Bryce Adelstein Lelbach, Mauro Bianco, Ben Sander, Athanasios Iliopoulos, John Michopoulos, Nevin Liber. 2022-07-13. MDSPAN.
https://wg21.link/p0009r18
[P2128R6] Corentin Jabot, Isabella Muerte, Daisy Hollman, Christian Trott, Mark Hoemmen. 2021-09-14. Multidimensional subscript operator.
https://wg21.link/p2128r6
[P2821R5] Jarrad J. Waterloo. 2023-12-18. span.at().
https://wg21.link/p2821r5