Created on 2025-08-13.00:00:00 last changed 2 weeks ago
Proposed resolution:
This wording is relative to N5014.
Modify [mdspan.layout.left.obs] as indicated:
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;-2- Constraints: […]
-3- Preconditions: […] -4- Effects: Let `P` be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>>is `true`. Equivalent to:
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
Modify [mdspan.layout.right.obs] as indicated:
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;-2- Constraints: […]
-3- Preconditions: […] -4- Effects: Let `P` be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>>is `true`. Equivalent to:
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
Modify [mdspan.layout.stride.obs] as indicated:
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;-2- Constraints: […]
-3- Preconditions: […] -4- Effects: Let `P` be a parameter pack such thatis_same_v<index_sequence_for<Indices...>, index_sequence<P...>>is `true`. Equivalent to:
return ((static_cast<index_type>(std::move(i)) * stride(P)) + ... + 0);
Modify [mdspan.layout.leftpad.obs] as indicated:
template<class... Indices> constexpr index_type operator()(Indices... idxs) const noexcept;-3- Constraints: […]
-4- Preconditions: […] -5- Returns: ((static_cast<index_type>(std::move(idxs)) * stride(P_rank)) + ... + 0).
Modify [mdspan.layout.rightpad.obs] as indicated:
template<class... Indices> constexpr index_type operator()(Indices... idxs) const noexcept;-3- Constraints: […]
-4- Preconditions: […] -5- Returns: ((static_cast<index_type>(std::move(idxs)) * stride(P_rank)) + ... + 0).
Modify [mdspan.layout.leftpad.cons] as indicated:
template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType padding);Let pad = static_cast<index_type>(std::move(padding)).
-3- Constraints: […] -4- Preconditions:
(4.1) — padding is representable as a value of type `index_type`.
(4.2) —
extents_type::index-cast(pad)pad is greater than zero.(4.3) — If rank_ is greater than one, then LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)) is representable as a value of type `index_type`.
(4.4) — If rank_ is greater than one, then the product of LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)) and all values ext.extent(k) with k in the range of [1, rank_) is representable as a value of type `index_type`.
(4.5) — If `padding_value` is not equal to `dynamic_extent`, `padding_value` equals
extents_type::index-cast(pad)pad.-5- Effects: […]
Modify [mdspan.layout.rightpad.cons] as indicated:
template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType padding);Let pad = static_cast<index_type>(std::move(padding)).
-3- Constraints: […] -4- Preconditions:
(4.1) — padding is representable as a value of type `index_type`.
(4.2) —
extents_type::index-cast(pad)pad is greater than zero.(4.3) — If rank_ is greater than one, then LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)) is representable as a value of type `index_type`.
(4.4) — If rank_ is greater than one, then the product of LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)) and all values ext.extent(k) with k in the range of [1, rank_ - 1) is representable as a value of type `index_type`.
(4.5) — If `padding_value` is not equal to `dynamic_extent`, `padding_value` equals
extents_type::index-cast(pad)pad.-5- Effects: […]
Numerous template classes in <mdspan> have template parameter `IndexType`. While this template parameter is restricted to be a signed or unsigned integer, these classes often accept user-defined classes that convert to `IndexType`.
They're either passed as an array/span of `OtherIndexType`; or as a template parameter pack. When passed as a template parameter pack, the common pattern istemplate<class... OtherIndexTypes> requires std::is_convertible_v<OtherIndexTypes, IndexType> && ... void dummy(OtherIndexTypes... indices) { something(static_cast<IndexType>(std::move(indices))...); }
This pattern allows passing in objects that convert to IndexType only as an rvalue reference, e.g.
class RValueInt { constexpr operator int() && noexcept { return m_int; } private: int m_int; };
This pattern can be found in:
a ctor of `extents`,
a ctor of `mdspan`,
`mdspan::operator[]`.
The five standardized layout mappings use a different pattern in their operator(), namely,
static_cast<IndexType>(indices)...
This prevents the passing in objects of type `RValueInt`, because the conversion isn't happening from an rvalue reference. This is addressed by Items 1 - 5 in the Proposed Resolution.
A different pattern can be found a ctor for `layout_{left,right}_padded`. Namely, directly passing an object of type `OtherIndexType` to LEAST-MULTIPLE-AT-LEAST. This is addressed in Items 6 and 7 in the Proposed Resolution. This inconsistency was noticed while fixing PR121061 and these changes have been applied to all layout mappings implemented in libstdc++.History | |||
---|---|---|---|
Date | User | Action | Args |
2025-08-16 13:52:51 | admin | set | messages: + msg14933 |
2025-08-13 00:00:00 | admin | create |