Add bounds-checked at() access to mdspan and mdarray

Summary

This merge request adds bounds-checked element access to the multidimensional array utilities:

  • Dune::Std::mdspan::at(...)
  • Dune::Std::mdarray::at(...)

The mdspan overloads follow the standard std::mdspan::at wording from P3383R3 and the current C++ working draft: they accept the same index forms as the unchecked subscript operators and throw std::out_of_range when the given multi-index is outside the extents.

mdarray gets the same checked-access interface for consistency with mdspan and with ordinary container-style at() access.

Motivation

Unchecked multidimensional access is appropriate in performance-sensitive inner loops, but user code and tests often need a defined failure mode for invalid indices. The new at() overloads provide that failure mode without changing the existing unchecked operator[] and operator() behavior.

This mirrors the standard direction for std::mdspan, where at() is the bounds-checked counterpart to multidimensional operator[].

Added API

For Dune::Std::mdspan, the new overloads are:

template <class... Indices>
constexpr reference at(Indices... indices) const;

template <class Index>
constexpr reference at(std::span<Index, extents_type::rank()> indices) const;

template <class Index>
constexpr reference at(
  const std::array<Index, extents_type::rank()>& indices) const;

For Dune::Std::mdarray, the same index forms are available as mutable and const overloads.

Implementation Notes

The bounds check is implemented in a small shared helper:

dune/common/std/impl/indices.hh

It provides Dune::Std::Impl::indexInIndexSpace(...), which checks whether a multi-index lies in the Cartesian index space:

[0, extent(0)) x ... x [0, extent(rank-1))

Both mdspan::at and mdarray::at use this helper before dispatching to the same mapping and accessor/container access paths as the unchecked accessors.

Tests

The existing tests are extended:

  • dune/common/std/test/mdspantest.cc
  • dune/common/std/test/mdarraytest.cc

They cover:

  • successful checked access for rank 0 through rank 3,
  • variadic, std::array, and std::span index forms,
  • std::out_of_range for negative indices,
  • std::out_of_range for indices equal to the corresponding extent,
  • mutable and const mdarray::at overloads.
Edited by Simon Praetorius

Merge request reports

Loading