3974. mdspan::operator[] should not copy OtherIndexTypes

Section: 24.7.3.6.3 [mdspan.mdspan.members] Status: WP Submitter: Casey Carter Opened: 2023-08-12 Last modified: 2023-11-22 16:02:17 UTC

Priority: Not Prioritized

View all issues with WP status.

Discussion:

The wording for mdspan's operator[] overloads that accept span and array is in 24.7.3.6.3 [mdspan.mdspan.members] paragraphs 5 and 6:

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

-5- Constraints:

  1. (5.1) — is_convertible_v<const OtherIndexType&, index_type> is true, and

  2. (5.2) — is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.

-6- Effects: Let P be a parameter pack such that

is_same_v<make_index_sequence<rank()>, index_sequence<P...>>

is true. Equivalent to:

return operator[](as_const(indices[P])...);

The equivalent code calls the other operator[] overload:

template<class... OtherIndexTypes>
  constexpr reference operator[](OtherIndexTypes... indices) const;

with a pack of const OtherIndexType lvalues, but we notably haven't required OtherIndexTypes to be copyable — we only require that we can convert them to index_type. While one could argue that the use in "Effects: equivalent to" implies a requirement of copyability, it's odd that this implicit requirement would be the only requirement for copyable OtherIndexTypes in the spec. We could fix this by changing the operator[] overload accepting OtherIndexTypes to take them by const&, but that would be inconsistent with virtually every other place in the spec where types convertible to index_type are taken by-value. I think the best localized fix is to perform the conversion to index_type in the "Effects: equivalent to" code so the actual arguments have type index_type which we know is copyable.

[2023-11-02; Reflector poll]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

[2023-11-11 Approved at November 2023 meeting in Kona. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4958.

  1. Modify 24.7.3.6.3 [mdspan.mdspan.members] as indicated:

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

    -5- Constraints:

    1. (5.1) — is_convertible_v<const OtherIndexType&, index_type> is true, and

    2. (5.2) — is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.

    -6- Effects: Let P be a parameter pack such that

    is_same_v<make_index_sequence<rank()>, index_sequence<P...>>
    

    is true. Equivalent to:

    return operator[](extents_type::index-cast(as_const(indices[P]))...);