|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4405" status="New"> |
| 5 | +<title>`mdspan` constructor should disallow derived to base conversions</title> |
| 6 | +<section> |
| 7 | +<sref ref="[mdspan.mdspan.cons]"/> |
| 8 | +</section> |
| 9 | +<submitter>Hewill Kang</submitter> |
| 10 | +<date>05 Oct 2025</date> |
| 11 | +<priority>99</priority> |
| 12 | + |
| 13 | +<discussion> |
| 14 | +<p> |
| 15 | +Unlike `ranges::subrange` or `span`, `mdspan` syntactically allows a multidimensional |
| 16 | +viewing base class via a derived class pointer (<a href="https://godbolt.org/z/c56h9fjs8">demo</a>): |
| 17 | +</p> |
| 18 | +<blockquote><pre> |
| 19 | +#include <span> |
| 20 | +#include <ranges> |
| 21 | +#include <mdspan> |
| 22 | + |
| 23 | +struct Base {}; |
| 24 | +struct Derived : Base {}; |
| 25 | +std::array<Derived, 12> arr; |
| 26 | +std::ranges::subrange<Base*> s(arr); // error, slicing |
| 27 | +std::span<Base> sp(arr.data(), arr.size()); // error, slicing |
| 28 | +std::mdspan<Base, std::dims<1>> msp(arr.data(), arr.size()); // <span style="color:#C80000;font-weight:bold">ok</span> |
| 29 | +</pre></blockquote> |
| 30 | +<p> |
| 31 | +Given that we intend to reject object slicing for both `default_accessor` and |
| 32 | +`aligned_accessor`, there seems no reason not to reject this invalid pointer |
| 33 | +arithmetic for `mdspan`. |
| 34 | +</p> |
| 35 | +</discussion> |
| 36 | + |
| 37 | +<resolution> |
| 38 | +<p> |
| 39 | +This wording is relative to <paper num="N5014"/>. |
| 40 | +</p> |
| 41 | + |
| 42 | +<blockquote class="note"> |
| 43 | +<p> |
| 44 | +[<i>Drafting note:</i> The exposition-only concept <code><i>convertible-to-non-slicing</i></code> comes from |
| 45 | +<sref ref="[range.subrange.general]"/>.] |
| 46 | +</p> |
| 47 | +</blockquote> |
| 48 | + |
| 49 | +<ol> |
| 50 | + |
| 51 | +<li><p>Modify <sref ref="[mdspan.mdspan.overview]"/> as indicated:</p> |
| 52 | + |
| 53 | +<blockquote> |
| 54 | +<pre> |
| 55 | +namespace std { |
| 56 | + template<class ElementType, class Extents, class LayoutPolicy = layout_right, |
| 57 | + class AccessorPolicy = default_accessor<ElementType>> |
| 58 | + class mdspan { |
| 59 | + public: |
| 60 | + using extents_type = Extents; |
| 61 | + using layout_type = LayoutPolicy; |
| 62 | + using accessor_type = AccessorPolicy; |
| 63 | + using mapping_type = typename layout_type::template mapping<extents_type>; |
| 64 | + using element_type = ElementType; |
| 65 | + using value_type = remove_cv_t<element_type>; |
| 66 | + using index_type = typename extents_type::index_type; |
| 67 | + using size_type = typename extents_type::size_type; |
| 68 | + using rank_type = typename extents_type::rank_type; |
| 69 | + using data_handle_type = typename accessor_type::data_handle_type; |
| 70 | + using reference = typename accessor_type::reference; |
| 71 | + […] |
| 72 | + template<class... OtherIndexTypes> |
| 73 | + constexpr explicit mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> ptr, OtherIndexTypes... exts); |
| 74 | + template<class OtherIndexType, size_t N> |
| 75 | + constexpr explicit(N != rank_dynamic()) |
| 76 | + mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, span<OtherIndexType, N> exts); |
| 77 | + template<class OtherIndexType, size_t N> |
| 78 | + constexpr explicit(N != rank_dynamic()) |
| 79 | + mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const array<OtherIndexType, N>& exts); |
| 80 | + constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const extents_type& ext); |
| 81 | + constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const mapping_type& m); |
| 82 | + constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const mapping_type& m, const accessor_type& a); |
| 83 | + […] |
| 84 | + }; |
| 85 | + […] |
| 86 | +} |
| 87 | +</pre> |
| 88 | +</blockquote> |
| 89 | +</li> |
| 90 | + |
| 91 | +<li><p>Modify <sref ref="[mdspan.mdspan.cons]"/> as indicated:</p> |
| 92 | + |
| 93 | +<blockquote> |
| 94 | +<pre> |
| 95 | +template<class... OtherIndexTypes> |
| 96 | + constexpr explicit mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, OtherIndexTypes... exts); |
| 97 | +</pre> |
| 98 | +<blockquote> |
| 99 | +<p> |
| 100 | +-4- Let `N` be `sizeof...(OtherIndexTypes)`. |
| 101 | +<p/> |
| 102 | +-5- <i>Constraints</i>: […] |
| 103 | +<p/> |
| 104 | +[…] |
| 105 | +</p> |
| 106 | +</blockquote> |
| 107 | +<pre> |
| 108 | +template<class OtherIndexType, size_t N> |
| 109 | + constexpr explicit(N != rank_dynamic()) |
| 110 | + mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, span<OtherIndexType, N> exts); |
| 111 | +template<class OtherIndexType, size_t N> |
| 112 | + constexpr explicit(N != rank_dynamic()) |
| 113 | + mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const array<OtherIndexType, N>& exts); |
| 114 | +</pre> |
| 115 | +<blockquote> |
| 116 | +<p> |
| 117 | +-8- <i>Constraints</i>: […] |
| 118 | +<p/> |
| 119 | +[…] |
| 120 | +</p> |
| 121 | +</blockquote> |
| 122 | +<pre> |
| 123 | +constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const extents_type& ext); |
| 124 | +</pre> |
| 125 | +<blockquote> |
| 126 | +<p> |
| 127 | +-11- <i>Constraints</i>: […] |
| 128 | +<p/> |
| 129 | +[…] |
| 130 | +</p> |
| 131 | +</blockquote> |
| 132 | +<pre> |
| 133 | +constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const mapping_type& m); |
| 134 | +</pre> |
| 135 | +<blockquote> |
| 136 | +<p> |
| 137 | +-14- <i>Constraints</i>: […] |
| 138 | +<p/> |
| 139 | +[…] |
| 140 | +</p> |
| 141 | +</blockquote> |
| 142 | +<pre> |
| 143 | +constexpr mdspan(<ins><i>convertible-to-non-slicing</i><</ins>data_handle_type<ins>> auto</ins> p, const mapping_type& m, const accessor_type& a); |
| 144 | +</pre> |
| 145 | +<blockquote> |
| 146 | +<p> |
| 147 | +-17- <i>Preconditions</i>: […] |
| 148 | +<p/> |
| 149 | +[…] |
| 150 | +</p> |
| 151 | +</blockquote> |
| 152 | +</blockquote> |
| 153 | +</li> |
| 154 | + |
| 155 | +</ol> |
| 156 | + |
| 157 | +</resolution> |
| 158 | + |
| 159 | +</issue> |
0 commit comments