Discussion:
Reusing storage of a subobject vs. activity of a union member
(too old to reply)
Language Lawyer
2018-09-02 12:10:59 UTC
Permalink
Recently I have written that
The lifetime ends when (a part) of an object storage is reused.
There is no such requirement that the pointer passed to the placement new shall have the value "pointer to an object" to end the lifetime of the object.
(https://groups.google.com/a/isocpp.org/d/msg/std-discussion/u5TafpMrNMU/ajkba852EQAJ)

But now I think that I could be wrong.

Consider the following code:

struct S { int i; int j; } s;
new (&s) int;

Does the last line end the lifetime of the `s` object???

[intro.object]/2 suggests that it is not:
If an object is created in storage associated with a member subobject or array
element e (which may or may not be within its lifetime), the created object is a subobject of e’s containing
object if:
— the lifetime of e’s containing object has begun and not ended, and
— the storage for the new object exactly overlays the storage location associated with e, and
— the new object is of the same type as e (ignoring cv-qualification).

The int object created by the placement new expression is created in storage associated with a member subobject, isn't it? Or not?

If it is, consider the following code:
union { int i; int j; } u;
new (&u) int;

Here, the int object is also created in storage associated with a member subobject... Wait, which one? `i` or `j`?
[class.union]/1: In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended (6.8).

Do both `i` and `j` refer to an object whose lifetime has begun and has not ended? It is impossible.
[class.union]/1: At most one of the non-static data members of an object of union type can be active at any time.


Any thoughts?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Language Lawyer
2018-09-03 09:06:59 UTC
Permalink
Post by Language Lawyer
Recently I have written that
The lifetime ends when (a part) of an object storage is reused.
There is no such requirement that the pointer passed to the placement new shall have the value "pointer to an object" to end the lifetime of the object.
(https://groups.google.com/a/isocpp.org/d/msg/std-discussion/u5TafpMrNMU/ajkba852EQAJ)
But now I think that I could be wrong.
struct S { int i; int j; } s;
new (&s) int;
Does the last line end the lifetime of the `s` object???
If an object is created in storage associated with a member subobject or array
element e (which may or may not be within its lifetime), the created object is a subobject of e’s containing
 — the lifetime of e’s containing object has begun and not ended, and
 — the storage for the new object exactly overlays the storage location associated with e, and
 — the new object is of the same type as e (ignoring cv-qualification).
The int object created by the placement new expression is created in storage associated with a member subobject, isn't it? Or not?
union { int i; int j; } u;
new (&u) int;
If it is not, one may consider the definition and examples of the "provides storage" term.
In the examples, the pointers to array elements are used with the placement new operator.
But storage is provided by the enclosing array.

Of course, there is a key difference between these examples.
Placement new in the struct/union examples replaces the subobject nominating its enclosing object.
In case of providing storage, the argument of the placement new nominates an element of an array (subobject) which will provide storage.

Objects can be nested within other objects, but the storage is "flat".
To preserve the status quo that at most one member of a union can be active at any time, it could be necessary to formalize how the flat storage that is to be reused is nominated.

This is not new. https://wg21.link/p0137r1 formalized how a union member shall be nominated in an assignment expression so that its lifetime could begin.
I think we need a similar rule for the argument of a placement new expression.

IMO the rules should be such that in the following code:
```
union { int i; int j; } u;
new (&u) int;
```
the placement new expression would end the lifetime of the union object.

I believe it would be natural to extend the rules for non-union classes.
For example, in the following code:
```
struct S { int i; int j; } s;
new (&s) int;
```
even though the placement new expression reuses the storage of the int subobject to create an object of the same type, it shall end the lifetime of the struct `s`, because the placement new expression does not nominate the member.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
h***@gmail.com
2018-09-04 14:12:02 UTC
Permalink
Post by Language Lawyer
Recently I have written that
The lifetime ends when (a part) of an object storage is reused.
There is no such requirement that the pointer passed to the placement
new shall have the value "pointer to an object" to end the lifetime of the
object.
Post by Language Lawyer
(
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/u5TafpMrNMU/ajkba852EQAJ)
Post by Language Lawyer
But now I think that I could be wrong.
struct S { int i; int j; } s;
new (&s) int;
Does the last line end the lifetime of the `s` object???
If an object is created in storage associated with a member subobject or
array
Post by Language Lawyer
element e (which may or may not be within its lifetime), the created
object is a subobject of e’s containing
Post by Language Lawyer
— the lifetime of e’s containing object has begun and not ended, and
— the storage for the new object exactly overlays the storage location
associated with e, and
Post by Language Lawyer
— the new object is of the same type as e (ignoring cv-qualification).
The int object created by the placement new expression is created in
storage associated with a member subobject, isn't it? Or not?
Post by Language Lawyer
union { int i; int j; } u;
new (&u) int;
If it is not, one may consider the definition and examples of the "provides storage" term.
In the examples, the pointers to array elements are used with the placement new operator.
But storage is provided by the enclosing array.
Of course, there is a key difference between these examples.
Placement new in the struct/union examples replaces the subobject
nominating its enclosing object.
In case of providing storage, the argument of the placement new nominates
an element of an array (subobject) which will provide storage.
Objects can be nested within other objects, but the storage is "flat".
To preserve the status quo that at most one member of a union can be
active at any time, it could be necessary to formalize how the flat storage
that is to be reused is nominated.
This is not new. https://wg21.link/p0137r1 formalized how a union member
shall be nominated in an assignment expression so that its lifetime could
begin.
I think we need a similar rule for the argument of a placement new expression.
```
union { int i; int j; } u;
new (&u) int;
```
the placement new expression would end the lifetime of the union object.
I believe it would be natural to extend the rules for non-union classes.
```
struct S { int i; int j; } s;
new (&s) int;
```
even though the placement new expression reuses the storage of the int
subobject to create an object of the same type, it shall end the lifetime
of the struct `s`, because the placement new expression does not nominate
the member.
I would love to get to this model, and perhaps we will if the "flat space"
version meets resistance when we move more things into constexpr-land. The
obstacle here is that placement-new is "just" an expression that invokes a
special allocation function that takes a void * placement parameter. There
is some amount of conceptual distance between what appears in the
*new-expression*, and what the allocation function receives as the
placement parameter. I've previously advocated (informally) for a typed
placement new allocation function precisely because the type of the object
being replaced is not part of the contract involved with placement-new.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
h***@gmail.com
2018-09-04 14:02:07 UTC
Permalink
Post by Language Lawyer
Recently I have written that
The lifetime ends when (a part) of an object storage is reused.
There is no such requirement that the pointer passed to the placement
new shall have the value "pointer to an object" to end the lifetime of the
object.
(
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/u5TafpMrNMU/ajkba852EQAJ)
But now I think that I could be wrong.
struct S { int i; int j; } s;
new (&s) int;
Does the last line end the lifetime of the `s` object???
If an object is created in storage associated with a member subobject or array
element e (which may or may not be within its lifetime), the created
object is a subobject of e’s containing
— the lifetime of e’s containing object has begun and not ended, and
— the storage for the new object exactly overlays the storage location
associated with e, and
— the new object is of the same type as e (ignoring cv-qualification).
The int object created by the placement new expression is created in
storage associated with a member subobject, isn't it? Or not?
union { int i; int j; } u;
new (&u) int;
Here, the int object is also created in storage associated with a member
subobject... Wait, which one? `i` or `j`?
[class.union]/1: In a union, a non-static data member is active if its
name refers to an object whose lifetime has begun and has not ended (6.8).
Do both `i` and `j` refer to an object whose lifetime has begun and has
not ended? It is impossible.
[class.union]/1: At most one of the non-static data members of an object
of union type can be active at any time.
Any thoughts?
We could probably apply the model that only one is active, but the answer
as to which collapses based on access. This might be something we want to
avoid as things move into the constexpr space. The notional rewrite
involved with access-by-common-initial-sequence suffers from the problem of
having to get this answer too, but I have not found the time to poke
further.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Continue reading on narkive:
Loading...