Hi folks,

I've written a draft proposal for `view_interface::at` in 

https://htmlpreview.github.io/?https://github.com/hewillk/view_interface-at/blob/main/view-at.html

any valuable comments are welcome, thanks.

Hewill

Hewill Kang <hewillk@gmail.com> 於 2023年11月13日 週一 下午6:10寫道:
Hey C++ folks,

I was surprised that C++26 actually introduced `.at()` 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