On Thu, Dec 4, 2025 at 10:35 PM Luc Grosheintz <[email protected]> wrote:
> Implements submdspan for layout_right_padded as described in P3663. > > PR libstdc++/110352 > > libstdc++-v3/ChangeLog: > > * include/std/mdspan (layout_right_padded::submdspan_mapping): > New friend method. > * testsuite/23_containers/mdspan/submdspan/submdspan.cc: > Instantiate test for layout_right_padded. > * testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc: > Ditto. > > Signed-off-by: Luc Grosheintz <[email protected]> > --- > Same comments as for previous patch. > libstdc++-v3/include/std/mdspan | 45 +++++++++++++++++++ > .../mdspan/submdspan/submdspan.cc | 7 ++- > .../mdspan/submdspan/submdspan_mapping.cc | 4 ++ > 3 files changed, 54 insertions(+), 2 deletions(-) > > diff --git a/libstdc++-v3/include/std/mdspan > b/libstdc++-v3/include/std/mdspan > index 21dbe6def22..269522f4a5a 100644 > --- a/libstdc++-v3/include/std/mdspan > +++ b/libstdc++-v3/include/std/mdspan > @@ -1353,40 +1353,76 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > constexpr auto __rank = _Extents::rank(); > constexpr auto __sta_exts > = __mdspan::__static_extents<_Extents>(_Us + 1, __rank); > if constexpr (!__mdspan::__all_static(__sta_exts)) > return dynamic_extent; > else > return __fwd_prod(__sta_exts); > } > > template<size_t _SubRank, size_t _Nm> > static consteval bool > _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> > __slice_kinds) > { > auto __rev_slice_kinds = array<_SliceKind, _Nm>{}; > for(size_t __i = 0; __i < _Nm; ++__i) > __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i]; > return __mdspan::__is_block<_SubRank>(span(__rev_slice_kinds)); > } > }; > > + template<> > + struct _SubMdspanMapping<_LayoutSide::__right, true> > + { > + using _Layout = layout_right; > + template<size_t _Pad> using _PaddedLayout = > layout_right_padded<_Pad>; > + > + template<typename _Mapping, size_t _Us> > + static consteval size_t > + _S_pad() > + { > + using _Extents = typename _Mapping::extents_type; > + constexpr auto __rank = _Extents::rank(); > + constexpr auto __sta_exts > + = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1); > + constexpr auto __sta_padstride > + = __mdspan::__get_static_stride<_Mapping>(); > + if constexpr (__sta_padstride == dynamic_extent > + || !__mdspan::__all_static(__sta_exts)) > + return dynamic_extent; > + else > + return __sta_padstride * __mdspan::__fwd_prod(__sta_exts); > + } > + > + template<size_t _SubRank, size_t _Nm> > + static consteval bool > + _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> > __slice_kinds) > + { > + if constexpr (_SubRank == 1) > Again, would peffer expressing this as in previous patch. > + return __slice_kinds[_Nm - 1] == > _SliceKind::__unit_strided_slice > + || __slice_kinds[_Nm - 1] == _SliceKind::__full; > + else > + return false; > + } > + }; > + > + > template<typename _Mapping> > constexpr auto > __submdspan_mapping_impl(const _Mapping& __mapping) > { return submdspan_mapping_result{__mapping, 0}; } > > template<typename _Mapping, typename... _Slices> > requires (sizeof...(_Slices) > 0) > constexpr auto > __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... > __slices) > { > constexpr auto __side = __mdspan::__mapping_side<_Mapping>(); > using _Trait = _SubMdspanMapping<__side, > __is_padded_mapping<_Mapping>>; > > constexpr auto __slice_kinds = > __mdspan::__make_slice_kind_array<_Slices...>(); > auto __offset = __mdspan::__suboffset(__mapping, __slices...); > auto __sub_exts = __mdspan::__subextents(__mapping.extents(), > __slices...); > using _SubExts = decltype(__sub_exts); > constexpr auto __sub_rank = _SubExts::rank(); > if constexpr (__sub_rank == 0) > return submdspan_mapping_result{ > @@ -2748,40 +2784,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > if constexpr (_S_rank <= 1) > return 1; > else if (__r == _S_rank - 1) > return 1; > else if (__r == _S_rank - 2) > return _M_padstride(); > else > return static_cast<index_type>( > static_cast<size_t>(_M_padstride()) * > static_cast<size_t>(__mdspan::__fwd_prod( > extents(), __r + 1, _S_rank - 1))); > } > > template<typename _RightPaddedMapping> > requires(__mdspan::__is_right_padded_mapping<_RightPaddedMapping> > && _RightPaddedMapping::extents_type::rank() == _S_rank) > friend constexpr bool > operator==(const mapping& __self, const _RightPaddedMapping& > __other) > noexcept > { return __self._M_storage._M_equal(__other); } > + > +#if __glibcxx_submdspan > + private: > + template<__mdspan::__acceptable_slice_type<index_type>... _Slices> > Will be in static_assert. > + requires (extents_type::rank() == sizeof...(_Slices)) > + friend constexpr auto > + submdspan_mapping(const mapping& __mapping, _Slices... __slices) > + { return __mdspan::__submdspan_mapping_impl(__mapping, > __slices...); } > +#endif // __glibcxx_submdspan > }; > #endif // __glibcxx_padded_layouts > > template<typename _ElementType> > struct default_accessor > { > static_assert(!is_array_v<_ElementType>, > "ElementType must not be an array type"); > static_assert(!is_abstract_v<_ElementType>, > "ElementType must not be an abstract class type"); > > using offset_policy = default_accessor; > using element_type = _ElementType; > using reference = element_type&; > using data_handle_type = element_type*; > > constexpr > default_accessor() noexcept = default; > > template<typename _OElementType> > diff --git > a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc > index 927b5d06c6b..f8382847fe3 100644 > --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan.cc > @@ -348,27 +348,30 @@ template<typename Layout> > }; > > run(std::extents(3, 5, 7)); > run(std::extents<int, 3, 5, 7>{}); > return true; > } > > template<typename Layout> > constexpr bool > test_all() > { > test_all_cheap<Layout>(); > test_all_expensive<Layout>(); > return true; > } > > int > main() > { > test_all<std::layout_left>(); > + test_all<std::layout_right>(); > + test_all<std::layout_stride>(); > test_all<std::layout_left_padded<1>>(); > test_all<std::layout_left_padded<8>>(); > test_all<std::layout_left_padded<dyn>>(); > - test_all<std::layout_right>(); > - test_all<std::layout_stride>(); > + test_all<std::layout_right_padded<1>>(); > + test_all<std::layout_right_padded<8>>(); > + test_all<std::layout_right_padded<dyn>>(); > return 0; > } > diff --git > a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc > index 50836968a06..efd71d10f9d 100644 > --- > a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc > +++ > b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc > @@ -273,25 +273,29 @@ template<typename Layout> > static_assert(test_layout_common_return_types<Layout>()); > > test_layout_padded_return_types<Layout>(); > static_assert(test_layout_padded_return_types<Layout>()); > > test_layout_padded_padding_value<Layout>(); > static_assert(test_layout_padded_padding_value<Layout>()); > return true; > } > > int > main() > { > test_return_types_unpadded_all<std::layout_left>(); > test_return_types_unpadded_all<std::layout_right>(); > > test_return_types_padded_all<std::layout_left_padded<1>>(); > test_return_types_padded_all<std::layout_left_padded<2>>(); > test_return_types_padded_all<std::layout_left_padded<dyn>>(); > > + test_return_types_padded_all<std::layout_right_padded<1>>(); > + test_return_types_padded_all<std::layout_right_padded<2>>(); > + test_return_types_padded_all<std::layout_right_padded<dyn>>(); > And to seprate cc files. > + > test_layout_stride_return_types(); > static_assert(test_layout_stride_return_types()); > return 0; > } > > -- > 2.52.0 > >
