C++ Logo

std-proposals

Advanced search

[std-proposals] Add `.at()` for `view_interface` (also along with `mdspan`)?

From: Hewill Kang <hewillk_at_[hidden]>
Date: Mon, 13 Nov 2023 18:10:21 +0800
Hey C++ folks,

I was surprised that C++26 actually introduced `.at()`
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2821r4.html> for
`span` (which throws an exception) , even though I was sure that this
function was initially rejected by the committee when `span` was first
introduced.
So, should `.at()` be also introduced for `view_interface` to ensure such
consistency, so that all range adaptors have safe random-access methods as
other containers in the standard?

```cpp
  template<class D>
  class view_interface {
  private:
    constexpr D& derived() noexcept {
      return static_cast<D&>(*this);
    }

  public:
    // [...]
    template<random_access_range R = D>
      constexpr decltype(auto) operator[](range_difference_t<R> n) {
        return ranges::begin(derived())[n];
      }

    template<random_access_range R = D> requires sized_range<D>
        constexpr decltype(auto) at(range_difference_t<R> n) {
          if (n < ranges::distance(derived()) || n >=
ranges::distance(derived()))
            throw_out_of_range();
          return operator[](n);
        }
  };
```

I believe this can be seen as an enhancement, as it enables range adaptors
to have safe random-access operations, which were not available before.
Additionally, `mdspan` also seems worth adding a corresponding variadic
`.at()`:

```cpp
  template<class ElementType, class Extents, class LayoutPolicy =
layout_right,
  class AccessorPolicy = default_accessor<ElementType>>
  class mdspan {
    // [mdspan.mdspan.members], members
    template<class... OtherIndexTypes>
      constexpr reference operator[](OtherIndexTypes... indices) const;
    template<class OtherIndexType>
      constexpr reference operator[](span<OtherIndexType, rank()> indices)
const;
    template<class OtherIndexType>
      constexpr reference operator[](const array<OtherIndexType, rank()>&
indices) const;

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

What do you guys think? Does introducing `.at()` for the above two have any
observable value?

Hewill

Received on 2023-11-13 10:10:34