C++ Logo

std-discussion

Advanced search

Re: [basic.life]#8 contradictions

From: Mykola Garkusha <garkusha.mykola_at_[hidden]>
Date: Mon, 2 Oct 2023 20:13:54 +0100
On Mon, Oct 2, 2023 at 2:58 PM Matthew House via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> On Mon, Oct 2, 2023 at 6:51 AM Mykola Garkusha via Std-Discussion
> <std-discussion_at_[hidden]> wrote:
> > Trying to make sense of the [basic.lifetime] section of the standard,
> but it
> > appears to be contradictive in a few places.
> >
> > While I'm generally I'm aware that there is work still going on to
> further
> > improve the standard, there is one particular contradiction that I
> haven't
> > seen covered. http://eel.is/c++draft/basic#life-8 places restrictions
> in case
> > the object lifetime ended but *before* the storage has been *released* or
> > *re-used*. While mentioning *released* makes sense, *re-used*, in my
> opinion,
> > brings contradiction since most often the new object would be created
> using
> > placement new, and now the latest standard does clearly mention that
> storage
> > is first released in placement new, and then the new object is created
> > [http://eel.is/c++draft/basic#life-1.5]
>
> A nitpick: storage is not *released* by a placement new-expression, it is
> only
> *reused* when the new-expression obtains storage for the new object.
>

 I did not mean to say that *release* was also happening. Was just saying
that *release* was non-contradictive and clear enough.


>
> > Wouldn't the drop of *re-used* from http://eel.is/c++draft/basic#life-8
> make
> > it non-contradictive? My reasoning is that as *re-used* is defined at
> least
> > for placement new (maybe memcpy as well?) the following code from the
> example
> > in [basic.life]#8
> >
> > this->~C(); // lifetime of *this ends
> > new (this) C(other); // new object of type C created. But why storage is
> not considered re-used given new rules in [basic.life]#1 around placement
> new
> >
> > would imply the following sequence of ordered events
> > (1) end of a lifetime for the object which this used to point to ->
> > (2) storage which this used to to point is *re-used* [basic.life]#1 ->
> > (3) new object C is created at the storage which is used to point to
> >
> > Then if the above is correct, the condition is in [basic.life]#8 cannot
> apply
> > to the corresponding example as (1) happens before (2) and (2) happens
> before
> > (3). Now if (2) would have been dropped as the required condition then it
> > would all make sense. However looks like from the comment in the example
> > above, that the standard omits *re-use* in "new (this) C(other"
> >
> > Any thoughts on this? Or I've missed some important piece in my
> reasoning?
> >
> > Kind Regards,
> > Mykola
>
> Simply removing "reused" from [basic.life]/8 would be overly broad: if the
> storage of a T object is reused for a U object, and then the storage of
> the U
> object is reused for another T object, then I don't think it's intended
> for the
> first T object to be transparently replaceable by the second. It would
> also have
> to say that only the first object to reuse the storage is eligible for
> transparently replacing the original object.
>
>
  Yeah, fair point actually. But could not it be said more explicitly that
this only applies to the next object to be created in the storage that the
original pointer pointed to, which would have made it clearer and
removed confusion?



> Otherwise, I agree that the wording is a bit weird. I think a lot of it
> comes
> down to when exactly the new object is *created*, which is the precise
> operation
> that [basic.life]/8 cares about. One possible interpretation can be
> derived from
> the wording of [intro.object]/10, where implicitly creating objects
> "creates and
> starts the lifetime" of those objects. If "starting the lifetime" of an
> object
> includes obtaining its storage per [basic.life]/(1.1), then this implies
> that
> creating an object occurs *before* obtaining its storage. Thus, under this
> reading, there is no contradiction in [basic.life]/8, since the storage
> hasn't
> yet been reused at the point when the new object is created.
>
> Note sure I follow your reasoning, that objects may be created before
obtaining storage. Each object has storage duration which is the property
it must have at creation [intro.object]/1. Although I am not fully clear
what is the formal definition of "obtaining storage". But even if objects
could be created before obtaining storage, that would only cover a few
cases: implicitly created objects and trivially constructible objects



> However, this is not as clear-cut for other methods of creating an object.
> For
> instance, it is very clear that new-expressions obtain storage
> ([basic.life]/1)
> and initialize the object ([expr.new]/21) only after the allocation
> function
> returns. But at what point does it create the object? The standard appears
> to be
> completely silent on this question. It would definitely be nice of the
> timing of
> object creation could be clarified in general.
>
>
[intro.object]/1 does tell when the object is created. To me, it means the
operations listed there create objects. To be created, those operations
must be complete as no extra information is given, which seems ok. But on
the other hand, the standard does mention now that re-use [
http://eel.is/c++draft/basic#life-1.5] of storage happens at some point
before or *at the time*(just trying to be conservative) the object is
created. But still the *re-use* would NOT happen before the object is
created so the whole [basic.life]/8 condition appears to be violated if
*re-use* is taken literally.


> Thank you,
> Matthew House
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>

Received on 2023-10-02 19:14:08