|
19778 | 19778 | template<class ElementType>
|
19779 | 19779 | class default_accessor;
|
19780 | 19780 |
|
| 19781 | + // \ref{mdspan.accessor.aligned}, class template \tcode{aligned_accessor} |
| 19782 | + template<class ElementType, size_t ByteAlignment> |
| 19783 | + class aligned_accessor; |
| 19784 | + |
19781 | 19785 | // \ref{mdspan.mdspan}, class template \tcode{mdspan}
|
19782 | 19786 | template<class ElementType, class Extents, class LayoutPolicy = layout_right,
|
19783 | 19787 | class AccessorPolicy = default_accessor<ElementType>>
|
@@ -23150,6 +23154,194 @@
|
23150 | 23154 | Equivalent to: \tcode{return p + i;}
|
23151 | 23155 | \end{itemdescr}
|
23152 | 23156 |
|
| 23157 | +\rSec4[mdspan.accessor.aligned]{Class template \tcode{aligned_accessor}} |
| 23158 | + |
| 23159 | +\rSec5[mdspan.accessor.aligned.overview]{Overview} |
| 23160 | + |
| 23161 | +\begin{codeblock} |
| 23162 | +namespace std { |
| 23163 | + template<class ElementType, size_t ByteAlignment> |
| 23164 | + struct @\libglobal{aligned_accessor}@ { |
| 23165 | + using offset_policy = default_accessor<ElementType>; |
| 23166 | + using element_type = ElementType; |
| 23167 | + using reference = ElementType&; |
| 23168 | + using data_handle_type = ElementType*; |
| 23169 | + |
| 23170 | + static constexpr size_t byte_alignment = ByteAlignment; |
| 23171 | + |
| 23172 | + constexpr aligned_accessor() noexcept = default; |
| 23173 | + template<class OtherElementType, size_t OtherByteAlignment> |
| 23174 | + constexpr aligned_accessor( |
| 23175 | + aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept; |
| 23176 | + template<class OtherElementType> |
| 23177 | + constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept; |
| 23178 | + |
| 23179 | + template<class OtherElementType> |
| 23180 | + constexpr operator default_accessor<OtherElementType>() const noexcept; |
| 23181 | + |
| 23182 | + constexpr reference access(data_handle_type p, size_t i) const noexcept; |
| 23183 | + |
| 23184 | + constexpr typename offset_policy::data_handle_type |
| 23185 | + offset(data_handle_type p, size_t i) const noexcept; |
| 23186 | + }; |
| 23187 | +} |
| 23188 | +\end{codeblock} |
| 23189 | + |
| 23190 | +\pnum |
| 23191 | +\mandates |
| 23192 | +\begin{itemize} |
| 23193 | +\item \tcode{byte_alignment} is a power of two and |
| 23194 | +\item \tcode{byte_alignment >= alignof(ElementType)} is \tcode{true}. |
| 23195 | +\end{itemize} |
| 23196 | + |
| 23197 | +\pnum |
| 23198 | +\tcode{aligned_accessor} meets the accessor policy requirements. |
| 23199 | + |
| 23200 | +\pnum |
| 23201 | +\tcode{ElementType} is required to be a complete object type |
| 23202 | +that is neither an abstract class type nor an array type. |
| 23203 | + |
| 23204 | +\pnum |
| 23205 | +Each specialization of \tcode{aligned_accessor} is |
| 23206 | +a trivially copyable type that models \libconcept{semiregular}. |
| 23207 | + |
| 23208 | +\pnum |
| 23209 | +\range{0}{$n$} is an accessible range |
| 23210 | +for an object \tcode{p} of type \tcode{data_handle_type} and |
| 23211 | +an object of type \tcode{aligned_accessor} if and only if |
| 23212 | +\begin{itemize} |
| 23213 | +\item |
| 23214 | +\range{p}{p + $n$} is a valid range and |
| 23215 | +\item |
| 23216 | +if $n$ is greater than zero, |
| 23217 | +then \tcode{is_sufficiently_aligned<byte_alignment>(p)} is \tcode{true}. |
| 23218 | +\end{itemize} |
| 23219 | + |
| 23220 | +\pnum |
| 23221 | +\begin{example} |
| 23222 | +The following function \tcode{compute} |
| 23223 | +uses \tcode{is_sufficiently_aligned} to check |
| 23224 | +whether a given \tcode{mdspan} with \tcode{default_accessor} has |
| 23225 | +a data handle with sufficient alignment |
| 23226 | +to be used with \tcode{aligned_accessor<float, 4 * sizeof(float)>}. |
| 23227 | +If so, the function dispatches to |
| 23228 | +a function \tcode{compute_using_fourfold_overalignment} |
| 23229 | +that requires fourfold over-alignment of arrays, |
| 23230 | +but can therefore use hardware-specific instructions, |
| 23231 | +such as four-wide SIMD (Single Instruction Multiple Data) instructions. |
| 23232 | +Otherwise, \tcode{compute} dispatches to a |
| 23233 | +possibly less optimized function \tcode{compute_without_requiring_overalignment} |
| 23234 | +that has no over-alignment requirement. |
| 23235 | +\begin{codeblock} |
| 23236 | +void compute_using_fourfold_overalignment( |
| 23237 | + std::mdspan<float, std::dims<1>, std::layout_right, |
| 23238 | + std::aligned_accessor<float, 4 * alignof(float)>> x); |
| 23239 | + |
| 23240 | +void compute_without_requiring_overalignment( |
| 23241 | + std::mdspan<float, std::dims<1>, std::layout_right> x); |
| 23242 | + |
| 23243 | +void compute(std::mdspan<float, std::dims<1>> x) { |
| 23244 | + constexpr auto byte_alignment = 4 * sizeof(float); |
| 23245 | + auto accessor = std::aligned_accessor<float, byte_alignment>{}; |
| 23246 | + auto x_handle = x.data_handle(); |
| 23247 | + |
| 23248 | + if (std::is_sufficiently_aligned<byte_alignment>(x_handle)) |
| 23249 | + compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); |
| 23250 | + else |
| 23251 | + compute_without_requiring_overalignment(x); |
| 23252 | +} |
| 23253 | +\end{codeblock} |
| 23254 | +\end{example} |
| 23255 | + |
| 23256 | +\rSec5[mdspan.accessor.aligned.members]{Members} |
| 23257 | + |
| 23258 | +\indexlibraryctor{aligned_accessor}% |
| 23259 | +\begin{itemdecl} |
| 23260 | +template<class OtherElementType, size_t OtherByteAlignment> |
| 23261 | + constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept; |
| 23262 | +\end{itemdecl} |
| 23263 | + |
| 23264 | +\begin{itemdescr} |
| 23265 | +\pnum |
| 23266 | +\constraints |
| 23267 | +\begin{itemize} |
| 23268 | +\item |
| 23269 | +\tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>} |
| 23270 | +is \tcode{true}. |
| 23271 | +\item |
| 23272 | +\tcode{OtherByteAlignment >= byte_alignment} is \tcode{true}. |
| 23273 | +\end{itemize} |
| 23274 | + |
| 23275 | +\pnum |
| 23276 | +\effects |
| 23277 | +None. |
| 23278 | +\end{itemdescr} |
| 23279 | + |
| 23280 | +\indexlibraryctor{aligned_accessor}% |
| 23281 | +\begin{itemdecl} |
| 23282 | +template<class OtherElementType> |
| 23283 | + constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept; |
| 23284 | +\end{itemdecl} |
| 23285 | + |
| 23286 | +\begin{itemdescr} |
| 23287 | +\pnum |
| 23288 | +\constraints |
| 23289 | +\tcode{is_convertible_v<OtherElementType(*)[], element_type(*)[]>} |
| 23290 | +is \tcode{true}. |
| 23291 | + |
| 23292 | +\pnum |
| 23293 | +\effects |
| 23294 | +None. |
| 23295 | +\end{itemdescr} |
| 23296 | + |
| 23297 | +\indexlibrarymember{access}{aligned_accessor}% |
| 23298 | +\begin{itemdecl} |
| 23299 | +constexpr reference access(data_handle_type p, size_t i) const noexcept; |
| 23300 | +\end{itemdecl} |
| 23301 | + |
| 23302 | +\begin{itemdescr} |
| 23303 | +\pnum |
| 23304 | +\expects |
| 23305 | +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. |
| 23306 | + |
| 23307 | +\pnum |
| 23308 | +\effects |
| 23309 | +Equivalent to: \tcode{return assume_aligned<byte_alignment>(p)[i];} |
| 23310 | +\end{itemdescr} |
| 23311 | + |
| 23312 | +\indexlibrarymember{operator default_accessor}{aligned_accessor}% |
| 23313 | +\begin{itemdecl} |
| 23314 | +template<class OtherElementType> |
| 23315 | + constexpr operator default_accessor<OtherElementType>() const noexcept; |
| 23316 | +\end{itemdecl} |
| 23317 | + |
| 23318 | +\begin{itemdescr} |
| 23319 | +\pnum |
| 23320 | +\constraints |
| 23321 | +\tcode{is_convertible_v<element_type(*)[], OtherElementType(*)[]>} |
| 23322 | +is \tcode{true}. |
| 23323 | + |
| 23324 | +\pnum |
| 23325 | +\effects |
| 23326 | +Equivalent to: \tcode{return \{\};} |
| 23327 | +\end{itemdescr} |
| 23328 | + |
| 23329 | +\indexlibrarymember{offset}{aligned_accessor}% |
| 23330 | +\begin{itemdecl} |
| 23331 | +constexpr typename offset_policy::data_handle_type |
| 23332 | + offset(data_handle_type p, size_t i) const noexcept; |
| 23333 | +\end{itemdecl} |
| 23334 | + |
| 23335 | +\begin{itemdescr} |
| 23336 | +\pnum |
| 23337 | +\expects |
| 23338 | +\range{0}{i + 1} is an accessible range for \tcode{p} and \tcode{*this}. |
| 23339 | + |
| 23340 | +\pnum |
| 23341 | +\effects |
| 23342 | +Equivalent to: \tcode{return assume_aligned<byte_alignment>(p) + i;} |
| 23343 | +\end{itemdescr} |
| 23344 | + |
23153 | 23345 | \rSec3[mdspan.mdspan]{Class template \tcode{mdspan}}
|
23154 | 23346 |
|
23155 | 23347 | \rSec4[mdspan.mdspan.overview]{Overview}
|
|
0 commit comments