C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [[packed]] std::unaligned

From: Thiago Macieira <thiago_at_[hidden]>
Date: Mon, 11 Dec 2023 21:14:09 -0500
On Monday, 11 December 2023 20:25:19 EST Frederick Virchanza Gotham via Std-
Proposals wrote:
> struct static_string {
> char buf[256u];
> char *plast;
> };
>
> And so if the string is 10 characters long, then 'plast' will be equal
> to 'this + 10 - 1'. The class is no longer trivially relocatable.

Strictly as above, no, it's still trivially relocatable. You need to add the
copy & move constructors to make it no longer trivially-relocatable. I assume
you omitted them for brevity.

> Arthur you said in your last post that I "never relocate-out-of (nor
> into) a `T`", but if you look at my implementation of the assignment
> operator (which I implemented as a template function), I do a memcpy
> to a suitably-aligned T-sized buffer and then perform an operation on
> it -- it is for this reason that I need T to be trivially relocatable.

That's not a trivial relocation. That's a trivial *copy*. The original object
is still there. It makes sense to add the ability to relocate out of a
std::unaligned. Semantically, it does not make sense to impose the requirement
on the contained type.

That said, since the type must be trivially copyable and movable, by
construction it will also be trivially relocatable. The three trivial
operations are the same: a memcpy.

> Anyway I've added a load of binary operators and unary operators to my
> previous code (adapted from Connor's code), and here's what I've got
> now:
>
> https://godbolt.org/z/z7MGMnzre

I think that's an unnecessary distraction for now. std::atomic has them, but
let's focus on the basics first.

> But even after we put together a robust implementation of
> std::unaligned (and I think we're getting close to it), I still want
> to be able to do:
>
> struct TokenInfo {
> long unsigned a;
> char b;
> long unsigned c;
> char d;
> };
>
> typedef struct TokenInfo [[packed]] TicketInfo;

I think that's a bad idea. This is a completely distinct type than the
original TokenInfo. It may make sense to have a std::deep_unaligned, which
would need to either wait for reflection or would require compiler support. At
which point it may be a keyword instead of a class or an attribute.

> Furthermore, I think that 'unaligned' should be compatible with
> 'optional'

It is compatible.

> so that you can do the following:
>
> std::optional<SomeClass> monkey;
> monkey.emplace(1,2,3,56.7L);
> std::unaligned<SomeClass> donkey( std::take_ownership_t(), monkey );

There's no such thing as std::take_ownership. You'll need to describe the
intent here, as we're not very good at diving it. What does it return? And if
it's not a SomeClass, why would std::unaligned have a constructor that can
receive it?

> Therefore the destructor of 'unaligned' would have to
> do something like:
>
> ~unaligned(void)
> {
> alignas(T) std::byte buf[ __datasizeof(T) ];
> T &tmp = *static_cast<T*>(static_cast<void*>(buf));
> std::memcpy(&tmp, &_m_data.front(), __datasizeof(T));
> tmp.~T();
> }

unalgined's destructor ought to be trivial. So the only implementation is

 = default

Even if not, your suggestion is not acceptable. Either the contained type has
a trivial destructor (as discussed before), in which case this is a no-op and
thus wholly unnecessary, or it isn't trivial and in which case the address may
matter. If it does matter, then the suggested destructor will cause
misbehaviour.

> Also another thing... I would want the 'unaligned' class to be derived
> from a base class such as:

Can't do it, because the base sub-object can't exist inside the derived
object, given the alignment constraints.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering

Received on 2023-12-12 02:14:24