Observations from implementing layout_left_padded.

Tomasz Kaminski tkaminsk@redhat.com
Thu Aug 21 16:16:13 GMT 2025


On Thu, Aug 21, 2025 at 5:31 PM Luc Grosheintz <luc.grosheintz@gmail.com>
wrote:

>
>
> On 8/21/25 12:19, Tomasz Kaminski wrote:
> > Hi,
> >
> > Now that we are done with all the other patches, I cleaned up my inbox,
> > and noticed that I haven't responded to this email.
> > I hope you are still interested in submitting patches for layouts,
>
> I was starting to think about using the PING feature. Yes, I've got
> "most" of this ready, so it feels wasteful to not finish it.
> (Other obligations and constant_wrapper interfered.)
>
Please do not hesitate to send a ping, if you do not get any response in
two weeks.
This mail may have been completely lost, if I wasn't careful with cleaning
the mdspan
related mails from my inbox, so ping would be very helpful.

>
> >
> > On Mon, Jun 30, 2025 at 10:34 AM Luc Grosheintz <
> luc.grosheintz@gmail.com>
> > wrote:
> >
> >> Dear libstdc++ developers,
> >>
> >> while implementing layout_left_padded, I noticed some unexpected
> >> behaviour and I'd like to ask for your input.
> >>
> >>
> >> 1. Odd mandate/prerequisite for padding value.
> >>
> >> The standard says the padding_value must be representable as
> >> index_type. This immediately precludes using `padding_value ==
> >> dynamic_extent` for any index_type < size_t [1]. Something
> >> similar happens in the ctors that accepts a padding value at
> >> runtime [2].
> >>
> > The padding value at runtime is never expected to be dynamic_extent (this
> > is only for static_extent),
> > so I think the [2] is correct.
>
> I agree, I don't understand anymore why I complained about [2].
>
> >
> > For the [1] I think we could be more lax, and incorporate it in the 5.3,
> > and saying that multiplication
> > of padding_value (if not dynamic) and 1 if ext.static_extent(0) is
> dynamic
> > of ext.static_extent(0) first
> > into index type. In other words we ignore padding values for ranks 0 and
> 1.
> > I would go for the above relaxed condition in the first implementation.
> >
>
> I'm not fully convinced we're understanding each other. I'll try
> an example:
>
> using Layout = std::layout_left_padded<std::dynamic_extent>;
> using Extent = std::extents<uint8_t, /* ... */>;
>
> // We can't write:
> Layout::mapping<Extents>
>
> because `padding_value` which is dynamic_extent, i.e. size_t(-1)
> is never representable as uint8_t; and then immediately violates
> the class mandate [1].
>
> Semantically, it doesn't seem right, because later we could still
> choose a perfectly suitable value (like `1`).
>
> If you look at the rest of the paper there's often this phrase:
>
>    If [...] padding_value does not equal dynamic_extent, then [...]
>
> I believe that that caveat is missing in [1].
>
> >
> >> Resolution: If padding_value != dynamic_extent, then ...
> >>
> >> [1]: https://eel.is/c++draft/mdspan.layout.leftpad#overview-5.2
> >> [2]: https://eel.is/c++draft/mdspan.layout.leftpad#cons-4.1
> >>
> >>
> >> 2. Not commonly-convertible.
> >>
> >> Usually, `Layout::mapping<E1>` can be converted to
> >> `Layout::mapping<E2>` if and only if `E1` can be converted to
> >> `E2`. Note that this is for different mappings of the same
> >> Layout.
> >>
> >> For layout_left_padded, the situation is different. If the
> >> extents differ, the following ctor [3] will be used:
> >>
> >>     template<typename _LeftPaddedMapping>
> >>       requires (...)
> >>       constexpr explicit(_S_rank > 1
> >>         && (padding_value != dynamic_extent
> >>           || _LeftPaddedMapping::padding_value == dynamic_extent))
> >>       mapping(const _LeftPaddedMapping& __other)
> >>
> >> Which means that, for rank > 1:
> >>
> >>     static_assert(!is_convertible_v<
> >>       layout_left_padded<2>::mapping<E1>,
> >>       layout_left_padded<2>::mapping<E2>);
> >>
> >> even if E1 and E2 are convertible.
> >>
> >> At the same time that ctor allows too many conversions if rank <= 1,
> >> including:
> >>
> >>     static_assert(!is_convertible_v<
> >>       layout_left_padded<2>::mapping<std::extents<int, dyn>>,
> >>       layout_left_padded<2>::mapping<std::extents<int, 1>>>);
> >>
> >>     static_assert(!is_convertible_v<
> >>       layout_left_padded<2>::mapping<std::extents<unsigned int, 1>>,
> >>       layout_left_padded<2>::mapping<std::extents<int, 1>>>);
> >>
> >> This second half, I've included in:
> >> https://cplusplus.github.io/LWG/issue4272
> >>
> >> But the issue that they don't convert regularly is unaddressed.
> >>
> >> Resolution 1: Allow conversion if:
> >>     - __is_layout_left_padded_mapping_of<_LeftPaddedMapping> is
> >>       true,
> >>     - same_as<layout_type,
> >>               typename _LeftPaddedMapping::layout_type> is true.
> >>
> >> and keep the current conditions otherwise.
> >>
> >> Resolution 2: Leave as is.
> >>
> > I would suggest for the first implementation, leave it as is currently.
> > Then it would be great if you could create a RFC patch showing the
> > difference
> > of behavior on existing tests.
>
> Okay, I'll first create the first implementation, then (much) later the
> RFC.
>
> >
> >>
> >> [3]: https://eel.is/c++draft/mdspan.layout.leftpad.cons#17
> >>
> >>
> >> 3. Generic Observation: Missing CTADs
> >>
> >> There's no deduction guides for mappings, e.g.:
> >>
> >>     std::layout_left::mapping(std::extents<int, 2>{});
> >>     std::layout_left_padded<1>::mapping m(ml); # Ugly error.
> >>
> > This seems like a feature request more than wording issue,
> > you could send the note to the paper authors of layouts. I find them very
> > responsive.
> >
>
> Definitely a feature request. I'll try if I can implement the deduction
> guide (I failed on my first try due to how mapping is nested inside another
> struct and gave up).
>
> >>
> >>
> >> Kind regards,
> >> Luc
> >>
> >>
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250821/ba2b48c8/attachment.htm>


More information about the Libstdc++ mailing list