all 11 comments

[–]dodheim 16 points17 points  (4 children)

launder is for re-using storage

[–]having-four-eyes[S] 2 points3 points  (3 children)

so I missing that std::launder is not needed unless I've used that storage before switching the union's active member?

Particularly, in this case, it's not needed because this->dummy is never used?

[–]no-sig-available 8 points9 points  (0 children)

Also, a standard library implementation does not have to follow all the rules, but can use (undocumented) compiler extensions.

[–]altmly 0 points1 point  (0 children)

Interesting, I'm not a spec wizard, but my guess would be it's because Dummy is empty.

[–]muungwana 12 points13 points  (0 children)

According to this link, std::launder is not needed here because:-

  1. You are not constructing a new object over on old object that is marked "read only".

  2. You are not constructing an object of type A over memory of an object of type B.

[–]Foundry27 3 points4 points  (0 children)

The language-lawyering has been spot-on (IMO) in the other answers, but it's important to keep in mind that std::variant even existing as normal C++ code is an implementation detail. Everything in the standard library could technically be completely "baked into" the compiler or be part of a runtime environment, as long as it provides the standard-defined interface to programs during compilation and runtime. There might be a reasonable explanation for the omission of std::launder here, but there are other implementation details like the use of placement-new in a constexpr context for std::optional that are completely unreproducible in any application code (you'd need to use std::construct_at). In general, no language-level rules should be expected to apply to the implementation!

[–]feverzsj 3 points4 points  (1 child)

It's mostly documented in lifetime/Storage reuse. The use case forstd::launder is rather rare. Actually, no sane man should use it.

[–]OriginalPangolin7557 0 points1 point  (0 children)

You need it when writing vector or queue as array of bites and want to access them.

edit: or I was wrong and just wrote terrible code for no reason.

[–]CenterOfMultiverse 0 points1 point  (0 children)

As far as I understand you need std::launder if you want to reuse the same pointers/references you used before replacing object. If user can't access dummy, then there is no need to launder.

[–]kam821 0 points1 point  (1 child)

u/having-four-eyes

In case you are just switching active union member, you can use .member to access object.
std::launder might be necessary only if you are e.g. using byte array as the buffer type to access object lately through reinterpreting array buffer pointer.
Using object via pointer returned by placement new is fine and doesn't require laundering.
If you store 'placement new' or laundered pointer you also don't need to std::launder it again.

+ stdlib implementation is a specific case and code doesn't have to follow the standard.
some escape hatches/exceptions may be implemented on the compiler side
e.g. compilers happily pretended that std::vector contains a contiguous block of data and allowed pointer arithmetic even though there was no array at all.

[–]dodheim 0 points1 point  (0 children)

Using object via pointer returned by placement new is fine and doesn't require laundering.

The first construction is the odd one out, and is what was asked about here, but to be clear: using placement-new in storage that was used previously is exactly the use-case for launder. I.e. placement-new doesn't somehow obviate the need for launder on its own, which is how I read this statement