mdspan
constructor should disallow derived to base conversionsSection: 23.7.3.6.2 [mdspan.mdspan.cons] Status: New Submitter: Hewill Kang Opened: 2025-10-05 Last modified: 2025-10-10
Priority: Not Prioritized
View all issues with New status.
Discussion:
Unlike ranges::subrange
or span
, mdspan
syntactically allows a multidimensional
viewing base class via a derived class pointer (demo):
#include <span>
#include <ranges>
#include <mdspan>
struct Base {};
struct Derived : Base {};
std::array<Derived, 12> arr;
std::ranges::subrange<Base*> s(arr); // error, slicing
std::span<Base> sp(arr.data(), arr.size()); // error, slicing
std::mdspan<Base, std::dims<1>> msp(arr.data(), arr.size()); // ok
Given that we intend to reject object slicing for both default_accessor
and
aligned_accessor
, there seems no reason not to reject this invalid pointer
arithmetic for mdspan
.
Proposed resolution:
This wording is relative to N5014.
[Drafting note: The exposition-only concept
convertible-to-non-slicing
comes from 25.5.4.1 [range.subrange.general].]
Modify 23.7.3.6.1 [mdspan.mdspan.overview] as indicated:
namespace std { template<class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor<ElementType>> class mdspan { public: using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping<extents_type>; using element_type = ElementType; using value_type = remove_cv_t<element_type>; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using data_handle_type = typename accessor_type::data_handle_type; using reference = typename accessor_type::reference; […] template<class... OtherIndexTypes> constexpr explicit mdspan(convertible-to-non-slicing<data_handle_type> auto ptr, OtherIndexTypes... exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(convertible-to-non-slicing<data_handle_type> auto p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(convertible-to-non-slicing<data_handle_type> auto p, const array<OtherIndexType, N>& exts); constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const extents_type& ext); constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const mapping_type& m); constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const mapping_type& m, const accessor_type& a); […] }; […] }
Modify 23.7.3.6.2 [mdspan.mdspan.cons] as indicated:
template<class... OtherIndexTypes> constexpr explicit mdspan(convertible-to-non-slicing<data_handle_type> auto p, OtherIndexTypes... exts);-4- Let
-5- Constraints: […] […]N
besizeof...(OtherIndexTypes)
.template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(convertible-to-non-slicing<data_handle_type> auto p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(convertible-to-non-slicing<data_handle_type> auto p, const array<OtherIndexType, N>& exts);-8- Constraints: […]
[…]constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const extents_type& ext);-11- Constraints: […]
[…]constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const mapping_type& m);-14- Constraints: […]
[…]constexpr mdspan(convertible-to-non-slicing<data_handle_type> auto p, const mapping_type& m, const accessor_type& a);-17- Preconditions: […]
[…]