Title
Inconsistency between the deduction guide of `std::mdspan` taking `(data_handle_type, mapping_type, accessor_type)` and the corresponding constructor
Status
new
Section
[mdspan.mdspan.overview]
Submitter
Jiang An

Created on 2026-01-09.00:00:00 last changed 3 days ago

Messages

Date: 2026-01-18.12:58:23

Proposed resolution:

This wording is relative to N5032.

  1. Modify [mdspan.mdspan.overview], class template mdspan synopsis, as indicated:

    namespace std {
      […]
      template<class MappingType, class AccessorType>
      mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
             const AccessorType&)
        -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
                  typename MappingType::layout_type, AccessorType>;
    }
    
Date: 2026-01-09.00:00:00

Currently, the following deduction guide of std::mdspan takes the data handle by reference:

template<class MappingType, class AccessorType>
  mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
         const AccessorType&)
    -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
              typename MappingType::layout_type, AccessorType>;

But the corresponding constructor takes the data handle by value:

constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);

The distinction is observable with `volatile` glvalues. E.g., in the following example, CTAD fails but explicitly specifying template arguments works (demo):

#include <cstddef>
#include <mdspan>

int main() {
  int a[1]{};
  int * volatile p = a;
  std::mdspan(
    p,
    std::layout_right::mapping<std::extents<std::size_t, 1>>{},
    std::default_accessor<int>{}); // error (but accidentally accepted by libc++)
  std::mdspan<int, std::extents<std::size_t, 1>>(
    p,
    std::layout_left::mapping<std::extents<std::size_t, 1>>{},
    std::default_accessor<int>{}); // OK
}

Given we're generally passing data handle by value, it seems better to remove const & from const typename AccessorType::data_handle_type& in the deduction guide, which is more consistent with the constructor and accept more seemingly valid uses.

Note that libc++ is accidentally doing this now by forgetting adding the &, see llvm/llvm-project#175024.

History
Date User Action Args
2026-01-18 12:58:23adminsetmessages: + msg15891
2026-01-09 00:00:00admincreate