C++ Logo

std-discussion

Advanced search

Re: Fwd: [basic.life]#8 contradictions

From: Mykola Garkusha <garkusha.mykola_at_[hidden]>
Date: Tue, 3 Oct 2023 00:56:37 +0100
  By the way, I'm referring latest C++ draft (http://eel.is/c++draft), not
the official C++20 standard, which may be a source of the confusion, as
there are edits there in [basic.life] not available in c++23. That is why I
keep mentioning there is a definition of "re-use" now which affected
placement new.

By saying an object has storage duration, I was meant to say that the
object also has storage and value, but lacked precision. Can *all* objects
be created without storage being obtained? What I'm trying to say more is
that not all objects can appear before their storage is obtained. For
example, for placement new to create an object, the storage must already be
allocated as it does not do allocation, and that is the central example of
[basic.life]/8. Also at least in [into.object]/3 it does mention "If a
complete object is created ([expr.new]) in storage ", which makes me infer
that being created is more physical and storage comes before creation,
although most likely not lifetime/initialization. Which by the way
technically gives a loophole to make [basic.life]/8 *non-contradictive* if
the object is meant to be "created" once its storage/storage duration/type
has been figured out! In that case, the re-use could happen after the
object is created given very peculiar wording around [new.expr] and the
*re-use* definition in
[basic.life]/1.5

Another point I'm trying to make is that is really about "being created"
which [basic.life]/8 refers to and which I infer to be clearly stated in
[intro.object]/1 as below as the *worst case*(*of course it could be
created earlier too*), AND NOT in [basic.life]/1.5 (that just defines
*re-use* I kept mentioning and which makes [basic.life]/8 contradictive in
my opinion)


The constructs in a C++ program create, destroy, refer to, access, and
manipulate objects. An object is created by a definition, by a
new-expression ([expr.new]), by an operation that implicitly creates
objects (see below), when implicitly changing the active member of a union,
or when a temporary object is created ([conv.rval], [class.temporary]). An
object occupies a region of storage in its period of construction
([class.cdtor]), throughout its lifetime, and in its period of destruction
([class.cdtor]).
[Note 1: A function is not an object, regardless of whether or not it
occupies storage in the way that objects do. — end note]




On Mon, Oct 2, 2023 at 11:02 PM Matthew House via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> On Mon, Oct 2, 2023 at 3:14 PM Mykola Garkusha
> <garkusha.mykola_at_[hidden]> wrote:
> > > 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?
>
> Yes, when I said that the paragraph should apply "only the first object to
> reuse
> the storage", I meant that it should be amended to include such an explicit
> remark (if "reused" is removed); my apologies if I was unclear.
>
> > > 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
>
> By [intro.object]/1, an object's storage duration is indeed determined at
> the
> point of creation. However, the *storage duration* is distinct from the
> *lifetime*, even though it influences the lifetime. As a property of an
> object,
> storage duration is effectively just an enum value, defined in
> [basic.stc]: an
> object has either static, thread, automatic, or dynamic storage duration.
> Meanwhile, nothing says that the lifetime itself is one of the properties
> determined on creation. Therefore, there is room for an interpretation
> where an
> object's storage duration is decided on creation, and only later is storage
> actually obtained as a prerequisite for initialization.
>
> As for a formal definition of *obtaining storage* for an object, I'd say
> it's a
> primitive operation defined primarily by its consequences. By my reading,
> obtaining storage for an object is what causes it to start occupying a
> region of
> storage and enter its period of construction, if we refer to
> [intro.object]/1.
> And by [basic.life]/(1.1), obtaining storage is a prerequisite for the
> lifetime
> of an object to start, so every operation that starts the lifetime of an
> object
> will also obtain storage for that object at some point. (This includes
> every
> operation that creates an object, since they all attempt to start its
> lifetime.)
> But even though it wouldn't make sense for creation to occur after the
> period of
> construction begins, it's not clear that creation doesn't occur *before*
> that
> period begins.
>
> > > 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.
>
> Alas, the wording of the standard is not very conducive to adding our own
> assumptions when no extra information is given. In this case, it doesn't
> really
> make sense to infer that the listed operations in [intro.object]/1 only
> create
> objects at the point of completion. Before it completes, a new-expression
> can
> call a user-defined constructor in order to initialize the new object. For
> the
> constructor to receive a 'this' pointer referring to the new object under
> construction, the new-expression must have already created that object and
> obtained its storage at some earlier point in time. Thus, at best, we can
> infer
> from [intro.object]/1 that the listed operations create objects at some
> unspecified point between their start and completion.
>
> Also, I don't see how you make that inference about object creation from
> [basic.life]/(1.5). That bullet only states that reusing storage for a new
> object causes the lifetime of any old object occupying that storage to
> end. (And
> again, by my reading, "reusing storage" is just a particular kind of
> "obtaining
> storage", which is just "causing an object to start occupying storage".) It
> doesn't appear to say anything at all about object *creation*?
>
> 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 23:56:51