what does "and/or not reassignable buffer" mean?

On Mon, Apr 29, 2019 at 11:54 AM Nicolas Lesser <blitzrakete@gmail.com> wrote:
Mohamed Khaled via Std-Discussion wrote:
> Hello All,
>
> ```
> #include <memory>
> #include <iostream>
>
> struct C
> {
>     const int x;
> };
>
> void foo1()
> {
>     C c{1};
>     c.~C();
>     new (&c) C{2};
>     std::cout << c.x << std::endl;
> }
>
> std::unique_ptr<C> foo2_a()
> {
>     std::unique_ptr<C> c(new C{1});
>     c->~C();
>     new (c.get()) C{2};
>     return c;
> }
>
> void foo2_b(std::unique_ptr<C> c)
> {
>     std::cout << c->x << std::endl;
> }
>
> int main()
> {
>     foo1();
>     foo2_b(foo2_a());
> }
> ```
>
> As far as I understand, in foo1() one should invoke std::launder whenever c
> is being accessed after the placement. Should it also be invoked in foo2_b,
> that is when the access to the object whose memory is being reused is in
> some separate function rather than the one where the placement happened.

std::launder is used only when you only have access to the new element through the old object, when for example the class has a const data member. In your case, you are right that in foo1 you should use std::launder. This *also* applies to foo2_b, since the pointer stored in the unique_ptr points to the old object and it can only be used to access the new object with std::launder.

> More generally should the placement new always be coupled with std::launder?

Not necessarely, only when you are using placement new on a variable and/or not reassignable buffer. If you use a pointer for example you can do this:

ptr = new (ptr) C{2};

And there you don't have to use placement new.

--
- Nicolas