C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::sizeof_minus_trailing_padding

From: Breno Guimarães <brenorg_at_[hidden]>
Date: Sun, 3 Dec 2023 14:38:53 -0300
What if someone memsets the content of the T inside the optional using the
size of the T?
Some people do that even though not always needed, but because paranoia is
good :D

Em dom., 3 de dez. de 2023 14:21, Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> escreveu:

> On Fri, Dec 1, 2023 at 11:38 PM Frederick Virchanza Gotham wrote:
> >
> > I think I just managed to write '__datasizeof' using portable standard
> C++:
>
>
> Actually it's UB to use 'offsetof' on some types.
>
> I'm going to make a second attempt at implementing '__datasizeof' in
> portable standard C++, this time without using 'offsetof' because it
> gives dodgy results with some types. (Go to:
> https://en.wikipedia.org/wiki/Offsetof and scroll down to
> 'Limitations').
>
> First and foremost, on implementations of C++ that ignore
> 'no_unique_address', this implementation of __datasizeof will always
> yield the same result as sizeof.
>
> So here's what I'll do. I shall add one byte to the end of T, see if
> the struct has expanded in size, then add another byte, then add
> another byte, then add another byte, until the size of the containing
> struct changes. I will find out how many bytes I need to add until the
> struct expands. So let's start off with a helper class:
>
> template<typename T, std::size_t count>
> class PlusBytes {
> [[no_unique_address]] T obj;
> char c[count];
> };
>
> And so then the implementation of a function to count the bytes of
> tail padding would be:
>
> template<typename T>
> consteval std::size_t tailpadding(void) noexcept
> {
> if ( sizeof(PlusBytes<T,1u>) > sizeof(T) ) return 0u;
> if ( sizeof(PlusBytes<T,2u>) > sizeof(T) ) return 1u;
> if ( sizeof(PlusBytes<T,3u>) > sizeof(T) ) return 2u;
> if ( sizeof(PlusBytes<T,4u>) > sizeof(T) ) return 3u;
> . . .
> . . .
> . . . // and on and on up as far as sizeof(T)-1
> }
>
> That looks pretty sturdy do me. Now we just have to replace that 'if'
> ladder with a fold expression. So we need a fold expression that works
> on an integer sequence going from 0 to sizeof(T)-2. So let's create
> our index sequence:
>
> template<typename T>
> consteval std::size_t tailpadding(void) noexcept
> {
> using IndexSeq = std::make_index_sequence<sizeof(T) - 1u>; //
> e.g. for 16, yields 0...14
> return tailpadding_detail<T>( IndexSeq{} );
> }
>
> Inside the implementation of 'tailpadding_detail', we will have a fold
> expression:
>
> template<typename T, std::size_t... numbers>
> consteval std::size_t
> tailpadding_detail(std::index_sequence<numbers...>) noexcept
> {
> if constexpr ( 0u == sizeof...(numbers) ) return 0u;
> else return (... + how_many_bytes<T,numbers>());
> }
>
> And finally we need to write a function called 'how_many_bytes' that
> will return 0 when we give it any other number than the amount of
> trailing padding bytes:
>
> template<typename T, std::size_t index_minus_one> // start at 1
> instead of 0
> consteval std::size_t how_many_bytes(void) noexcept // thus
> 0...14 becomes 1...15
> {
> constexpr std::size_t index = index_minus_one + 1u;
>
> // Check if this one expanded the struct or not
> if ( sizeof(PlusBytes<T,index>) == sizeof(T) ) return 0u;
>
> // Check if previous one expanded the struct or not
> if ( sizeof(PlusBytes<T,index - 1u>) > sizeof(T) ) return 0u;
>
> return index - 1u;
> }
>
> Then we would write 'datasizeof' as follows:
>
> template<typename T>
> consteval std::size_t datasizeof(void) noexcept
> {
> return sizeof(T) - tailpadding<T>();
> }
>
> Here it is all together on GodBolt working with g++, clang++ and Intel icx:
>
> https://godbolt.org/z/KWb419M4T
>
> This implementation of 'datasizeof' can then be used to write an
> 'std::optional' class that puts the flag inside tail padding:
>
> https://godbolt.org/z/aP6xP5zzT
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-12-03 17:39:52