This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4511. Inconsistency between the deduction guide of std::mdspan taking (data_handle_type, mapping_type, accessor_type) and the corresponding constructor

Section: 23.7.3.6.1 [mdspan.mdspan.overview] Status: New Submitter: Jiang An Opened: 2026-01-09 Last modified: 2026-01-18

Priority: Not Prioritized

View other active issues in [mdspan.mdspan.overview].

View all other issues in [mdspan.mdspan.overview].

View all issues with New status.

Discussion:

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.

Proposed resolution:

This wording is relative to N5032.

  1. Modify 23.7.3.6.1 [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>;
    }