Open mhoemmen opened 1 year ago
submdspan
lets you take subsets of a an mdspan
An example:
// Some data representing 2x3 matrices
double data[6] = { 11, 12, 13,
21, 22, 23 };
// An rank-2 mdspan of the data
mdspan matrix(data, 2, 3);
mdspan<double,extents<size_t, dynamic_extent>, layout_stride>
col_0 = submdspan(matrix, full_extent, 0);
// col_0 == 11, 21
// col_0.stride(0) == 3
mdspan<double,extents<size_t, dynamic_extent>, layout_right>
row_1 = submdspan(matrix, 1, full_extent);
// row_1 == 21, 22, 23
// row_1.stride(0) == 1
// in practice this is a place where auto is your friend:
auto row_0 = submdspan(matrix, 0, full_extent);
submdspan
in our proposal is effectively implemented as:
// submdspan takes and mdspan and slice specifiers
template<class T, class E, class L, class A, class ... SliceArgs)
auto submdspan(const mdspan<T,E,L,A>& src, SliceArgs ... args) {
// get the new accessor from the old one
typename A::offset_policy sub_acc(src.accessor());
// get new mapping as well as linear offset from submdspan_mapping
// This function is a customization point and will be called using ADL!
// returns an aggregate type "submdspan_mapping_result"
auto sub_map = submdspan_mapping(src.mapping(), args...);
// Check that we didn't get an invalid submdspan_mapping impl
#ifndef NDEBUG
// submdspan_extents is NOT a customization point.
auto expected_extents = submdspan_extents(src.extents(), args...);
// check that the types match
static_assert(is_same_v<decltype(sub_map.mapping)::extent_type,
decltype(expected_extents)>);
// check that the values match
assert(expected_extents==sub_map.mapping.extents());
#endif
// Compute the new data handle
auto sub_handle = src.accessor().offset(src.data_handle(), sub_map.offset);
// return the new mdspan
return mdspan(sub_handle, sub_map.mapping, sub_acc);
}
submdspan_mapping
Changed from pair to a specific named aggregate type.
Before:
template<class Extents, class... SliceSpecifiers>
constexpr auto submdspan_mapping(
const layout_left::mapping<Extents>& src,
SliceSpecifiers ... slices) {
...
return pair{new_mapping, offset};
}
Now:
template<class LayoutMapping>
struct submdspan_mapping_result {
LayoutMapping mapping;
size_t offset;
};
template<class Extents, class... SliceSpecifiers>
constexpr auto submdspan_mapping(
const layout_left::mapping<Extents>& src,
SliceSpecifiers ... slices) {
...
return submdspan_mapping_result{new_mapping, offset};
}
submdspan_mapping
directly - mostly folks will call submdspan
submdspan_mapping
only needs to be implemented for custom layout mappings, a rare use casesubmdspan_mapping
has no default implementation (unlike, say, std::swap
)swap
friend member is meant to be used with std::swap
?submdspan_mapping
is a very non-general name - in particular in its overload which takes a mapping and slice specifiers.submdspan_mapping
, all of which can be checked.
extents_type
is mandatedextents()
values are mandated.begin
function is generally T::iterator_type
etc.submdspan_mapping
none of the arguments know anything about the return type. The return type is really a combinatorical property of all the arguments.
layout_left
mapping but the output is a layout_stride
mapping
auto sub = submdspan_mapping(layout_left::mapping(4,4), 0, full_extent);
layout_left
mappingGodBolt example of custom layout/accessor in combo with submdspan: https://godbolt.org/z/EhMrYvTfo
P2630R2: submdspan
submdspan: multidimensional array slicing
Split from P0009 after LEWG review
P2630 expands facility to make it work for custom layouts, and adds
strided_slice
R2 changes
Added discussion choice of customization point mechanism
Renamed
strided_index_range
tostrided_slice
Introduced named struct combining mapping and offset as return type for
submdspan_mapping
Removed redundant constraints, which are covered by mandates; this improves error messages for users
Customization point mechanism
Paper: Section 2.1.3 "Pure ADL vs. CPO vs. tag invoke"
Applies P2279's criteria to judge value of different mechanisms
Most users will never call
submdspan_mapping
directlysubmdspan_mapping
only needs to be implemented for custom layout mappings, a rare use casesubmdspan_mapping
has no default implementation (unlike, say,std::swap
)Name
submdspan_mapping
is extremely specific, making opt-in essentially explicitIncorrect opt-in is easy to diagnose: return type must be a layout mapping with specific extents
This and other discussion in paper suggest no significant benefits in preferring CPOs or
tag_invoke
over pure ADL forsubmdspan_mapping
. However, we would accept LEWG's preference fortag_invoke
here.