From 74547154a98c4dcd8aa4c29cc5e2e0dbc22f2f25 Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Thu, 2 Apr 2026 20:36:56 +0200 Subject: [PATCH 1/3] P3982R2 Split strided_slice into extent_slice and range_slice for C++26 (1/2) Fixes NB PL 007 (C++26 CD). Part 1 of 2: Adds the new range_slice wording. Editorial notes: * [mdspan.sub.overview] Add missing article "the". * [mdspan.sub.range.slices] Insert comma before "respectively". * [mdspan.sub.helpers] Remove excessive sub-itemizations. --- source/containers.tex | 186 ++++++++++++++++++++++++++++++------------ source/support.tex | 2 +- 2 files changed, 136 insertions(+), 52 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index e8f86c09c9..9f88343dd6 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -21299,6 +21299,8 @@ // \ref{mdspan.sub}, \tcode{submdspan} creation template struct strided_slice; + template> + struct range_slice; template struct submdspan_mapping_result; @@ -25573,7 +25575,13 @@ \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting \tcode{$S$::offset_type}, \tcode{$S$::extent_type}, and - \tcode{$S$::stride_type}; or + \tcode{$S$::stride_type}; +\item + $S$ is a specialization of \tcode{range_slice} and + \tcode{is_convertible_v} is \tcode{true} for $X$ denoting type of + \tcode{$S$::first}, + \tcode{$S$::last}, and + \tcode{$S$::stride} members; or \item all of the following hold: \begin{itemize} @@ -25650,6 +25658,10 @@ \item \range{$0$}{e.extent($k$)}, if \tcode{S} is \tcode{full_extent_t}; +\item + \range{E::index_type(s.offset)}{E::index_type(s.offset)}, + if \tcode{S} is a specialization of \tcode{strided_slice} and + \tcode{E::index_type(s.extent)} is zero; otherwise \item \range{E::index_type(s.offset)}{E::index_type(s.offset + s.extent)}, if \tcode{S} is a specialization of \tcode{stri\-ded_slice}; otherwise @@ -25669,16 +25681,30 @@ if \tcode{S} is a specialization of \tcode{strided_slice}: \begin{itemize} \item - if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper}, - then \tcode{S::offset_type::value} is less than or equal to $x$; + $o$ is less than or equal to $x$; \item - if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper}, - then \tcode{S::extent_type::value} is less than or equal to $x$; and + $e$ is less than or equal to $x$; \item - if both \tcode{S::offset_type} and \tcode{S::extent_type} - are specializations of \tcode{constant_wrapper}, - then \tcode{S::offset_type::value + S::extent_type::value} - is less than or equal to $x$; or + if $e$ is greater than one, + then $t$ is greater than zero, + \item + if $e$ is greater than zero, + then $o + 1 + (e - 1) * t$ is less than or equal to $x$ + \end{itemize} + where + \begin{itemize} + \item + $o$ is the value of \tcode{S::offset_type::value} + if \tcode{S::offset_type} is a specialization of \tcode{constant_wrapper} and + \tcode{0} otherwise, + \item + $e$ is the value of \tcode{S::extent_type::value} + if \tcode{S::extend_type} is a specialization of \tcode{constant_wrapper} and + \tcode{0} otherwise, + \item + $t$ is the value of \tcode{S::stride_type::value} + if \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and + \tcode{1} otherwise. \end{itemize} \item if $S$ is a specialization of \tcode{constant_wrapper}, @@ -25703,19 +25729,20 @@ if \tcode{S} is a specialization of \tcode{strided_slice}, then: \begin{itemize} \item \tcode{s.extent} is greater than or equal to zero, and - \item either \tcode{s.extent} equals zero or \tcode{s.stride} is greater than zero. + \item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero. \end{itemize} \end{itemize} -\rSec4[mdspan.sub.strided.slice]{\tcode{strided_slice}} +\rSec4[mdspan.sub.range.slices]{\tcode{Range slices}} \pnum -\tcode{strided_slice} represents a set of +\tcode{strided_slice} and \tcode{range_slice} represent a set of \tcode{extent} regularly spaced integer indices. -The indices start at \tcode{offset}, and +The indices start at \tcode{offset} and \tcode{first}, respectively, and increase by increments of \tcode{stride}. \indexlibraryglobal{strided_slice}% +\indexlibraryglobal{range_slice}% \begin{codeblock} namespace std { template @@ -25728,21 +25755,31 @@ [[no_unique_address]] extent_type extent{}; [[no_unique_address]] stride_type stride{}; }; + + template> + struct range_slice { + [[no_unique_address]] FirstType first{}; + [[no_unique_address]] LastType last{}; + [[no_unique_address]] StrideType stride{}; + }; } \end{codeblock} \pnum -\tcode{strided_slice} has the data members and special members specified above. -It has no base classes or members other than those specified. +\tcode{strided_slice} and \tcode{range_slice} +have the data members and special members specified above. +They have no base classes or members other than those specified. \pnum \mandates -\tcode{OffsetType}, \tcode{ExtentType}, and \tcode{StrideType} +\tcode{OffsetType}, \tcode{ExtentType}, +\tcode{FirstType}, \tcode{LastType}, and \tcode{StrideType} are signed or unsigned integer types, or model \exposconcept{integral-constant-like}. \begin{note} -\tcode{strided_slice\{.offset = 1, .extent = 10, .stride = 3\}} -indicates the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}. +Both \tcode{strided_slice\{.offset = 1, .extent = 4, .stride = 3\}} and +\tcode{range_slice\{.first = 1, .last = 11, .stride = 3\}} +indicate the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}. Indices are selected from the half-open interval \range{1}{1 + 10}. \end{note} @@ -25792,6 +25829,18 @@ if \tcode{T} is a specialization of \tcode{strided_slice}. \end{itemdescr} +\begin{itemdecl} +template + concept @\defexposconcept{is-range-slice}@ = @\seebelow;@ +\end{itemdecl} + +\begin{itemdescr} +\pnum +The concept \tcode{\exposconcept{is-range-slice}} +is satisfied and modeled if and only +if \tcode{T} is a specialization of \tcode{range_slice}. +\end{itemdescr} + \indexlibraryglobal{\exposid{canonical-index}}% \begin{itemdecl} template @@ -25822,6 +25871,53 @@ \end{itemize} \end{itemdescr} +\begin{itemdecl} +template + constexpr auto @\exposid{canonical-range-slice}@(OffsetType offset, SpanType span, StrideTypes... strides); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item + \tcode{StrideType} denote + \tcode{constant_wrapper} + if \tcode{StrideTypes} is an empty pack or + \tcode{SpanType} denotes \tcode{constant_wrapper}, otherwise + \tcode{StrideTypes...[0]}; +\item + \tcode{stride} be + \tcode{StrideType()} if \tcode{StrideType} + is a specialization of \tcode{constant_wrapper}, otherwise + \tcode{IndexType(1)} if \tcode{span == 0} is \tcode{true}, otherwise + \tcode{strides...[0]}; +\item + \exposid{extent-value} be \tcode{1 + (span - 1) / stride} + if \tcode{span != 0} is \tcode{true}, and + \tcode{0} otherwise; +\item + \tcode{extent} be \tcode{cw} + if both \tcode{SpanType} and \tcode{StrideType} + are specializations of \tcode{constant_wrapper}, and + \tcode{IndexType(\exposid{extent-value})} otherwise. +\end{itemize} + +\pnum +\mandates +\tcode{sizeof...(StrideTypes) <= 1} is \tcode{true}, and +if \tcode{StrideType} is a specialization of \tcode{con\-stant_wrapper}, +then \tcode{StrideType::value > 0} is \tcode{true}. + +\pnum +\expects +\tcode{stride > 0} is \tcode{true}. + +\pnum +\returns +\tcode{strided_slice\{.offset = offset, .extent = extent, .stride = stride\};} +\end{itemdescr} + \indexlibraryglobal{\exposid{canonical-slice}} \begin{itemdecl} template @@ -25842,30 +25938,25 @@ } else if constexpr (is_convertible_v) { return @\exposid{canonical-index}@(std::move(s)); } else if constexpr (@\exposconcept{is-strided-slice}@) { - auto c_extent = @\exposid{canonical-index}@(std::move(s.extent)); - auto c_offset = @\exposid{canonical-index}@(std::move(s.offset)); - if constexpr (is_same_v>) { - return strided_slice{ - .offset = c_offset, - .extent = c_extent, - .stride = cw - }; - } else { - return strided_slice{ - .offset = c_offset, - .extent = c_extent, - .stride = @\exposid{canonical-index}@(std::move(s.stride)) - }; - } + return strided_slice{ + .offset = @\exposid{canonical-index}@(std::move(s.extent)), + .extent = @\exposid{canonical-index}@(std::move(s.offset)), + .stride = @\exposid{canonical-index}@(std::move(s.stride)) + }; +} else if constexpr (@\exposid{is-range-slice}@) { + auto c_first = canonical-index(std::move(s.first)); + auto c_last = canonical-index(std::move(s.last)); + return @\exposid{canonical-slice-range}@( + c_first, + @\exposid{canonical-index}@(c_last - c_first), + @\exposid{canonical-index}@(std::move(s.stride))); } else { auto [s_first, s_last] = std::move(s); auto c_first = @\exposid{canonical-index}@(std::move(s_first)); auto c_last = @\exposid{canonical-index}@(std::move(s_last)); - return strided_slice{ - .offset = c_first, - .extent = @\exposid{canonical-index}@(c_last - c_first), - .stride = cw - }; + return @\exposid{canonical-slice-range}@( + c_first, + @\exposid{canonical-index}@(c_last - c_first)); } \end{codeblock} \end{itemdescr} @@ -25956,7 +26047,7 @@ \tcode{\placeholder{MAP_RANK}(slices, Extents::rank())}; and \item -for each rank index $k$ of \tcode{Extents} such that +for each rank index $k$ of \tcode{extents} such that the type of \tcode{slices...[$k$]} is not a collapsing slice type, \tcode{SubExt\-ents::static_extent(\placeholder{MAP_RANK}(slices, $k$))} equals the following, where $\Sigma_k$ @@ -25965,20 +26056,13 @@ \begin{itemize} \item \tcode{Extents::static_extent($k$)} - if $\Sigma_k$ denotes the \tcode{full_extent_t}; - otherwise - - \item - \tcode{0}, - if $\Sigma_k$ is a specialization of \tcode{strided_slice} and - \tcode{$\Sigma_k$::extent_type} denotes \tcode{constant_wrapper}; + if $\Sigma_k$ denotes \tcode{full_extent_t}; otherwise \item - \tcode{1 + (($\Sigma_k$::extent_type::value - 1) / $\Sigma_k$::stride_type::value)}, + \tcode{$\Sigma_k$::extent_type::value} if $\Sigma_k$ is a specialization of \tcode{strided_slice} whose - \tcode{extent_type} and \tcode{stride_type} - denote specializations of \tcode{constant_wrapper}; + \tcode{extent_type} denotes a specialization of \tcode{constant_wrapper}; \item otherwise, @@ -25996,7 +26080,7 @@ where $\sigma_k$ denotes \tcode{slices...[$k$]}: \begin{itemize} \item - \tcode{$\sigma_k$.extent == 0 ? 0 : 1 + ($\sigma_k$.extent - 1) / $\sigma_k$.stride} + \tcode{$\sigma_k$.extent} if the type of $\sigma_k$ is a specialization of \tcode{strided_slice}, \item otherwise, @@ -26161,7 +26245,7 @@ \item \tcode{stride(k) * s.stride} if the type of \tcode{s} is a specialization of \tcode{strided_slice} and -\tcode{s.stride < s.ex\-tent} is \tcode{true}, +\tcode{s.extent > 1} is \tcode{true}, where \tcode{s} is \tcode{slices...[$k$]}; \item otherwise, \tcode{stride($k$)}. diff --git a/source/support.tex b/source/support.tex index ef8c036b31..655a9c948d 100644 --- a/source/support.tex +++ b/source/support.tex @@ -858,7 +858,7 @@ #define @\defnlibxname{cpp_lib_string_subview}@ 202506L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} -#define @\defnlibxname{cpp_lib_submdspan}@ 202511L // freestanding, also in \libheader{mdspan} +#define @\defnlibxname{cpp_lib_submdspan}@ 202603L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{iosfwd}, \libheader{syncstream} #define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding} From 71ef679255069fa25d9038a58985c37b8f248c27 Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Thu, 2 Apr 2026 20:39:22 +0200 Subject: [PATCH 2/3] P3982R2 Split strided_slice into extent_slice and range_slice for C++26 (2/2) Part 2 of 2: Renames "strided_slice" to "extent_slice". --- source/containers.tex | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 9f88343dd6..bf1f827579 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -21298,7 +21298,7 @@ // \ref{mdspan.sub}, \tcode{submdspan} creation template - struct strided_slice; + struct extent_slice; template> struct range_slice; @@ -25571,7 +25571,7 @@ \item \tcode{is_convertible_v<$S$, IndexType>} is \tcode{true}; \item - $S$ is a specialization of \tcode{strided_slice} and + $S$ is a specialization of \tcode{extent_slice} and \tcode{is_convertible_v<$X$, IndexType>} is \tcode{true} for $X$ denoting \tcode{$S$::offset_type}, \tcode{$S$::extent_type}, and @@ -25614,7 +25614,7 @@ \item $S$ is a canonical \tcode{submdspan} index type for \tcode{IndexType}; or \item - $S$ is a specialization of \tcode{strided_slice} + $S$ is a specialization of \tcode{extent_slice} where all of the following hold: \begin{itemize} \item @@ -25630,7 +25630,7 @@ \pnum A type \tcode{S} is a \defnadj{collapsing}{slice type} if it is neither \tcode{full_extent_t} nor -a specialization of \tcode{strided_slice}. +a specialization of \tcode{extent_slice}. \begin{note} Each collapsing slice type in \tcode{submdspan_mapping}'s parameter pack of slice specifier types @@ -25641,7 +25641,7 @@ A type \tcode{S} is a \defnadj{unit-stride}{slice type} if \begin{itemize} \item - \tcode{S} is a specialization of \tcode{strided_slice} + \tcode{S} is a specialization of \tcode{extent_slice} where \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and \tcode{S::stride_type::value} is equal to 1, or \item @@ -25660,7 +25660,7 @@ if \tcode{S} is \tcode{full_extent_t}; \item \range{E::index_type(s.offset)}{E::index_type(s.offset)}, - if \tcode{S} is a specialization of \tcode{strided_slice} and + if \tcode{S} is a specialization of \tcode{extent_slice} and \tcode{E::index_type(s.extent)} is zero; otherwise \item \range{E::index_type(s.offset)}{E::index_type(s.offset + s.extent)}, @@ -25678,7 +25678,7 @@ either $x$ is equal to \tcode{dynamic_extent}; or \begin{itemize} \item - if \tcode{S} is a specialization of \tcode{strided_slice}: + if \tcode{S} is a specialization of \tcode{extent_slice}: \begin{itemize} \item $o$ is less than or equal to $x$; @@ -25726,7 +25726,7 @@ contains the \tcode{submdspan} slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}; and \item - if \tcode{S} is a specialization of \tcode{strided_slice}, then: + if \tcode{S} is a specialization of \tcode{extent_slice}, then: \begin{itemize} \item \tcode{s.extent} is greater than or equal to zero, and \item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero. @@ -25736,17 +25736,17 @@ \rSec4[mdspan.sub.range.slices]{\tcode{Range slices}} \pnum -\tcode{strided_slice} and \tcode{range_slice} represent a set of +\tcode{extent_slice} and \tcode{range_slice} represent a set of \tcode{extent} regularly spaced integer indices. The indices start at \tcode{offset} and \tcode{first}, respectively, and increase by increments of \tcode{stride}. -\indexlibraryglobal{strided_slice}% +\indexlibraryglobal{extent_slice}% \indexlibraryglobal{range_slice}% \begin{codeblock} namespace std { template - struct strided_slice { + struct extent_slice { using offset_type = OffsetType; using extent_type = ExtentType; using stride_type = StrideType; @@ -25766,7 +25766,7 @@ \end{codeblock} \pnum -\tcode{strided_slice} and \tcode{range_slice} +\tcode{extent_slice} and \tcode{range_slice} have the data members and special members specified above. They have no base classes or members other than those specified. @@ -25777,7 +25777,7 @@ are signed or unsigned integer types, or model \exposconcept{integral-constant-like}. \begin{note} -Both \tcode{strided_slice\{.offset = 1, .extent = 4, .stride = 3\}} and +Both \tcode{extent_slice\{.offset = 1, .extent = 4, .stride = 3\}} and \tcode{range_slice\{.first = 1, .last = 11, .stride = 3\}} indicate the indices \tcode{1}, \tcode{4}, \tcode{7}, and \tcode{10}. Indices are selected from the half-open interval \range{1}{1 + 10}. @@ -25819,14 +25819,14 @@ \begin{itemdecl} template - concept @\defexposconcept{is-strided-slice}@ = @\seebelow;@ + concept @\defexposconcept{is-extent-slice}@ = @\seebelow;@ \end{itemdecl} \begin{itemdescr} \pnum -The concept \tcode{\exposconcept{is-strided-slice}} +The concept \tcode{\exposconcept{is-extent-slice}} is satisfied and modeled if and only -if \tcode{T} is a specialization of \tcode{strided_slice}. +if \tcode{T} is a specialization of \tcode{extent_slice}. \end{itemdescr} \begin{itemdecl} @@ -25915,7 +25915,7 @@ \pnum \returns -\tcode{strided_slice\{.offset = offset, .extent = extent, .stride = stride\};} +\tcode{extent_slice\{.offset = offset, .extent = extent, .stride = stride\};} \end{itemdescr} \indexlibraryglobal{\exposid{canonical-slice}} @@ -25937,8 +25937,8 @@ return static_cast(std::move(s)); } else if constexpr (is_convertible_v) { return @\exposid{canonical-index}@(std::move(s)); -} else if constexpr (@\exposconcept{is-strided-slice}@) { - return strided_slice{ +} else if constexpr (@\exposconcept{is-extent-slice}@) { + return extent_slice{ .offset = @\exposid{canonical-index}@(std::move(s.extent)), .extent = @\exposid{canonical-index}@(std::move(s.offset)), .stride = @\exposid{canonical-index}@(std::move(s.stride)) @@ -26061,7 +26061,7 @@ \item \tcode{$\Sigma_k$::extent_type::value} - if $\Sigma_k$ is a specialization of \tcode{strided_slice} whose + if $\Sigma_k$ is a specialization of \tcode{extent_slice} whose \tcode{extent_type} denotes a specialization of \tcode{constant_wrapper}; \item @@ -26081,7 +26081,7 @@ \begin{itemize} \item \tcode{$\sigma_k$.extent} - if the type of $\sigma_k$ is a specialization of \tcode{strided_slice}, + if the type of $\sigma_k$ is a specialization of \tcode{extent_slice}, \item otherwise, $U - L$, where \range{$L$}{$U$} is the \tcode{submdspan} slice range @@ -26119,7 +26119,7 @@ \item \tcode{IT}, \item \tcode{full_extent_t}, \item a specialization of \tcode{constant_wrapper}, or - \item a specialization of \tcode{strided_slice}. + \item a specialization of \tcode{extent_slice}. \end{itemize} \end{itemize} @@ -26244,7 +26244,7 @@ \begin{itemize} \item \tcode{stride(k) * s.stride} -if the type of \tcode{s} is a specialization of \tcode{strided_slice} and +if the type of \tcode{s} is a specialization of \tcode{extent_slice} and \tcode{s.extent > 1} is \tcode{true}, where \tcode{s} is \tcode{slices...[$k$]}; \item From 6d2e0d96d0279d52360c0cacbed7d3d10feb71af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Sun, 19 Apr 2026 18:08:25 +0100 Subject: [PATCH 3/3] [mdspan.sub.overview] Fix punctuation in list items. Multiple lists are part of one long sentence. --- source/containers.tex | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index bf1f827579..e6ebac5b24 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -25678,7 +25678,7 @@ either $x$ is equal to \tcode{dynamic_extent}; or \begin{itemize} \item - if \tcode{S} is a specialization of \tcode{extent_slice}: + if \tcode{S} is a specialization of \tcode{extent_slice}, then \begin{itemize} \item $o$ is less than or equal to $x$; @@ -25689,7 +25689,7 @@ then $t$ is greater than zero, \item if $e$ is greater than zero, - then $o + 1 + (e - 1) * t$ is less than or equal to $x$ + then $o + 1 + (e - 1) * t$ is less than or equal to $x$, \end{itemize} where \begin{itemize} @@ -25704,7 +25704,7 @@ \item $t$ is the value of \tcode{S::stride_type::value} if \tcode{S::stride_type} is a specialization of \tcode{constant_wrapper} and - \tcode{1} otherwise. + \tcode{1} otherwise; and \end{itemize} \item if $S$ is a specialization of \tcode{constant_wrapper}, @@ -25726,7 +25726,7 @@ contains the \tcode{submdspan} slice range of \tcode{s} for the $k^\text{th}$ extent of \tcode{e}; and \item - if \tcode{S} is a specialization of \tcode{extent_slice}, then: + if \tcode{S} is a specialization of \tcode{extent_slice}, then \begin{itemize} \item \tcode{s.extent} is greater than or equal to zero, and \item either \tcode{s.extent} is less than two or \tcode{s.stride} is greater than zero. @@ -25878,7 +25878,7 @@ \begin{itemdescr} \pnum -Let: +Let \begin{itemize} \item \tcode{StrideType} denote @@ -25895,9 +25895,9 @@ \item \exposid{extent-value} be \tcode{1 + (span - 1) / stride} if \tcode{span != 0} is \tcode{true}, and - \tcode{0} otherwise; + \tcode{0} otherwise; and \item - \tcode{extent} be \tcode{cw} + let \tcode{extent} be \tcode{cw} if both \tcode{SpanType} and \tcode{StrideType} are specializations of \tcode{constant_wrapper}, and \tcode{IndexType(\exposid{extent-value})} otherwise.