Date: Fri, 11 Sep 2020 00:33:17 +0200
In your example, the whole struct is replaced, so that the condition is
easily fulfilled by the old and new S object both being complete objects,
and the part with p1 and p2 isn't required, I think.
In my example, however, only a subobject is replaced. After some
consideration, I think jim x is probably right that they can be the same.
It would be weird if such a simple replacement wasn't intended to be
defined anymore, when it worked in c++17. However, I think some
consideration should be given to the beginning of [basic.life]/8 in
general. Strictly speaking, it describes the situation in which such a
replacement is possible as:
"If, *after the lifetime of an object has ended and before the storagewhich
the object occupied is reused* or released, a new object is created at the
storage location which the original object occupied."
But technically, the lifetime of the old object was only ended *because*
its storage was reused. It could be interpreted in such a way that it is
required to explicitly end the lifetime of the old object (by calling a
destructor) *before* the placement-new expression. I saw an SO post in
which a pretty reputable user interpreted it in this way and inferred the
following?
struct X {int i; float j;} x;
int& ir = x.i;
x.~X();
new (&x) X{};
bool b = ir == 5; // well-defined
new (&x) X{};
b = ir == 5; // undefiend because lifetime of X wasn't ended so
basic.life/8 doesn't apply.
Is this a sensible interpretation? If that was true than it might not be
possible to replace non-class objects at all. (Unless the psedo-destructor
ends their lifetime? :/ )
Am Do., 10. Sept. 2020 um 12:30 Uhr schrieb <language.lawyer_at_[hidden]>:
I think, p1 p2 must be the old and the new objects, they can't be the same
object.
I assume p1 and p2 are needed for the following code:
struct S { int i; };
S s {};
int& ri = s.i;
new (&s) S {};
where the wording guarantees that `ri` will refer to the new int subobject
(o2) of the object of type S (p2)
On 10/09/2020 12:43, jim x via Std-Discussion wrote:
> I think your first opinion is the intent of the rule. Because, according
> to the rule [intro.object#2] <https://eel.is/c++draft/intro.object#2>,
the
> new object has became the subobject of the object X, and the condition "o1
> and o2 are direct subobjects of objects P1 and P2" is true. The standard
> does not say `P1` and `P2` shall not be the same object, the object
> `X` itself satisfies all rules listed in [basic.life#8]
> <https://eel.is/c++draft/basic.life#8>. So, there's no necessary to use
> `std::launder`.
>
> John Mousseau via Std-Discussion <std-discussion_at_[hidden]>
> 于2020年9月9日周三 上午1:49写道:
>
>> Dear list members,
>>
>> in draft N4860 <https://isocpp.org/files/papers/N4860.pdf>, which I
>> assume is close to C++20, the wording of [basic.life]/8 differs from
C++17
>> in that the notion of "transparently replaceable" was involved. I am
>> wondering whether condition 8.5 of that paragraph allows for p1 and p2 to
>> be the same object.
>>
>> Consider the following most trivial example:
>>
>> struct X {int i; float f;};
>> X x{3, 3.f};
>> new(&x.i) int(5);
>> // x.i == 5 without launder? True in C++17.
>>
>> According to C++17's wording this is surely the case as there is no
>> const-qualification involved at all. However, in the newest wording,
while
>> conditions (8.1) through (8.4) are fulfilled (for o1 and o2 being the old
>> and new int respectively), condition (8.5) might be unfulfilled, as
neither
>> are both objects complete, nor are they subobjects of (different) objects
>> p1 and p2, unless, by [intro.object]/2, the new int becomes a subobject
of
>> x, and when then consider p1 and p2 of [basic.life]/8.5 to be identical.
If
>> we then consider x to be transparently-replaceable by itself, the
condition
>> would be fulfilled. Is that the intended interpretation or is the
intention
>> that the access in my example now requires std::launder even though no
>> constness is involved?
>>
>> Sorry in case I am not seeing the obvious and thank you for your time.
>>
>> Best Regards
>> John Mousseau
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
>
>
Am Do., 10. Sept. 2020 um 12:30 Uhr schrieb <language.lawyer_at_[hidden]>:
> I think, p1 p2 must be the old and the new objects, they can't be the same
> object.
> I assume p1 and p2 are needed for the following code:
>
> struct S { int i; };
>
> S s {};
> int& ri = s.i;
>
> new (&s) S {};
>
>
> where the wording guarantees that `ri` will refer to the new int subobject
> (o2) of the object of type S (p2)
>
>
> On 10/09/2020 12:43, jim x via Std-Discussion wrote:
> > I think your first opinion is the intent of the rule. Because, according
> > to the rule [intro.object#2] <https://eel.is/c++draft/intro.object#2>,
> the
> > new object has became the subobject of the object X, and the condition
> "o1
> > and o2 are direct subobjects of objects P1 and P2" is true. The standard
> > does not say `P1` and `P2` shall not be the same object, the object
> > `X` itself satisfies all rules listed in [basic.life#8]
> > <https://eel.is/c++draft/basic.life#8>. So, there's no necessary to use
> > `std::launder`.
> >
> > John Mousseau via Std-Discussion <std-discussion_at_[hidden]>
> > 于2020年9月9日周三 上午1:49写道:
> >
> >> Dear list members,
> >>
> >> in draft N4860 <https://isocpp.org/files/papers/N4860.pdf>, which I
> >> assume is close to C++20, the wording of [basic.life]/8 differs from
> C++17
> >> in that the notion of "transparently replaceable" was involved. I am
> >> wondering whether condition 8.5 of that paragraph allows for p1 and p2
> to
> >> be the same object.
> >>
> >> Consider the following most trivial example:
> >>
> >> struct X {int i; float f;};
> >> X x{3, 3.f};
> >> new(&x.i) int(5);
> >> // x.i == 5 without launder? True in C++17.
> >>
> >> According to C++17's wording this is surely the case as there is no
> >> const-qualification involved at all. However, in the newest wording,
> while
> >> conditions (8.1) through (8.4) are fulfilled (for o1 and o2 being the
> old
> >> and new int respectively), condition (8.5) might be unfulfilled, as
> neither
> >> are both objects complete, nor are they subobjects of (different)
> objects
> >> p1 and p2, unless, by [intro.object]/2, the new int becomes a subobject
> of
> >> x, and when then consider p1 and p2 of [basic.life]/8.5 to be
> identical. If
> >> we then consider x to be transparently-replaceable by itself, the
> condition
> >> would be fulfilled. Is that the intended interpretation or is the
> intention
> >> that the access in my example now requires std::launder even though no
> >> constness is involved?
> >>
> >> Sorry in case I am not seeing the obvious and thank you for your time.
> >>
> >> Best Regards
> >> John Mousseau
> >> --
> >> Std-Discussion mailing list
> >> Std-Discussion_at_[hidden]
> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> >>
> >
> >
>
easily fulfilled by the old and new S object both being complete objects,
and the part with p1 and p2 isn't required, I think.
In my example, however, only a subobject is replaced. After some
consideration, I think jim x is probably right that they can be the same.
It would be weird if such a simple replacement wasn't intended to be
defined anymore, when it worked in c++17. However, I think some
consideration should be given to the beginning of [basic.life]/8 in
general. Strictly speaking, it describes the situation in which such a
replacement is possible as:
"If, *after the lifetime of an object has ended and before the storagewhich
the object occupied is reused* or released, a new object is created at the
storage location which the original object occupied."
But technically, the lifetime of the old object was only ended *because*
its storage was reused. It could be interpreted in such a way that it is
required to explicitly end the lifetime of the old object (by calling a
destructor) *before* the placement-new expression. I saw an SO post in
which a pretty reputable user interpreted it in this way and inferred the
following?
struct X {int i; float j;} x;
int& ir = x.i;
x.~X();
new (&x) X{};
bool b = ir == 5; // well-defined
new (&x) X{};
b = ir == 5; // undefiend because lifetime of X wasn't ended so
basic.life/8 doesn't apply.
Is this a sensible interpretation? If that was true than it might not be
possible to replace non-class objects at all. (Unless the psedo-destructor
ends their lifetime? :/ )
Am Do., 10. Sept. 2020 um 12:30 Uhr schrieb <language.lawyer_at_[hidden]>:
I think, p1 p2 must be the old and the new objects, they can't be the same
object.
I assume p1 and p2 are needed for the following code:
struct S { int i; };
S s {};
int& ri = s.i;
new (&s) S {};
where the wording guarantees that `ri` will refer to the new int subobject
(o2) of the object of type S (p2)
On 10/09/2020 12:43, jim x via Std-Discussion wrote:
> I think your first opinion is the intent of the rule. Because, according
> to the rule [intro.object#2] <https://eel.is/c++draft/intro.object#2>,
the
> new object has became the subobject of the object X, and the condition "o1
> and o2 are direct subobjects of objects P1 and P2" is true. The standard
> does not say `P1` and `P2` shall not be the same object, the object
> `X` itself satisfies all rules listed in [basic.life#8]
> <https://eel.is/c++draft/basic.life#8>. So, there's no necessary to use
> `std::launder`.
>
> John Mousseau via Std-Discussion <std-discussion_at_[hidden]>
> 于2020年9月9日周三 上午1:49写道:
>
>> Dear list members,
>>
>> in draft N4860 <https://isocpp.org/files/papers/N4860.pdf>, which I
>> assume is close to C++20, the wording of [basic.life]/8 differs from
C++17
>> in that the notion of "transparently replaceable" was involved. I am
>> wondering whether condition 8.5 of that paragraph allows for p1 and p2 to
>> be the same object.
>>
>> Consider the following most trivial example:
>>
>> struct X {int i; float f;};
>> X x{3, 3.f};
>> new(&x.i) int(5);
>> // x.i == 5 without launder? True in C++17.
>>
>> According to C++17's wording this is surely the case as there is no
>> const-qualification involved at all. However, in the newest wording,
while
>> conditions (8.1) through (8.4) are fulfilled (for o1 and o2 being the old
>> and new int respectively), condition (8.5) might be unfulfilled, as
neither
>> are both objects complete, nor are they subobjects of (different) objects
>> p1 and p2, unless, by [intro.object]/2, the new int becomes a subobject
of
>> x, and when then consider p1 and p2 of [basic.life]/8.5 to be identical.
If
>> we then consider x to be transparently-replaceable by itself, the
condition
>> would be fulfilled. Is that the intended interpretation or is the
intention
>> that the access in my example now requires std::launder even though no
>> constness is involved?
>>
>> Sorry in case I am not seeing the obvious and thank you for your time.
>>
>> Best Regards
>> John Mousseau
>> --
>> Std-Discussion mailing list
>> Std-Discussion_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>>
>
>
Am Do., 10. Sept. 2020 um 12:30 Uhr schrieb <language.lawyer_at_[hidden]>:
> I think, p1 p2 must be the old and the new objects, they can't be the same
> object.
> I assume p1 and p2 are needed for the following code:
>
> struct S { int i; };
>
> S s {};
> int& ri = s.i;
>
> new (&s) S {};
>
>
> where the wording guarantees that `ri` will refer to the new int subobject
> (o2) of the object of type S (p2)
>
>
> On 10/09/2020 12:43, jim x via Std-Discussion wrote:
> > I think your first opinion is the intent of the rule. Because, according
> > to the rule [intro.object#2] <https://eel.is/c++draft/intro.object#2>,
> the
> > new object has became the subobject of the object X, and the condition
> "o1
> > and o2 are direct subobjects of objects P1 and P2" is true. The standard
> > does not say `P1` and `P2` shall not be the same object, the object
> > `X` itself satisfies all rules listed in [basic.life#8]
> > <https://eel.is/c++draft/basic.life#8>. So, there's no necessary to use
> > `std::launder`.
> >
> > John Mousseau via Std-Discussion <std-discussion_at_[hidden]>
> > 于2020年9月9日周三 上午1:49写道:
> >
> >> Dear list members,
> >>
> >> in draft N4860 <https://isocpp.org/files/papers/N4860.pdf>, which I
> >> assume is close to C++20, the wording of [basic.life]/8 differs from
> C++17
> >> in that the notion of "transparently replaceable" was involved. I am
> >> wondering whether condition 8.5 of that paragraph allows for p1 and p2
> to
> >> be the same object.
> >>
> >> Consider the following most trivial example:
> >>
> >> struct X {int i; float f;};
> >> X x{3, 3.f};
> >> new(&x.i) int(5);
> >> // x.i == 5 without launder? True in C++17.
> >>
> >> According to C++17's wording this is surely the case as there is no
> >> const-qualification involved at all. However, in the newest wording,
> while
> >> conditions (8.1) through (8.4) are fulfilled (for o1 and o2 being the
> old
> >> and new int respectively), condition (8.5) might be unfulfilled, as
> neither
> >> are both objects complete, nor are they subobjects of (different)
> objects
> >> p1 and p2, unless, by [intro.object]/2, the new int becomes a subobject
> of
> >> x, and when then consider p1 and p2 of [basic.life]/8.5 to be
> identical. If
> >> we then consider x to be transparently-replaceable by itself, the
> condition
> >> would be fulfilled. Is that the intended interpretation or is the
> intention
> >> that the access in my example now requires std::launder even though no
> >> constness is involved?
> >>
> >> Sorry in case I am not seeing the obvious and thank you for your time.
> >>
> >> Best Regards
> >> John Mousseau
> >> --
> >> Std-Discussion mailing list
> >> Std-Discussion_at_[hidden]
> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
> >>
> >
> >
>
Received on 2020-09-10 17:37:01