Topic: Thoughts about relocation
Author: florian.csdt@gmail.com
Date: Fri, 10 Aug 2018 09:41:31 -0700 (PDT)
Raw View
------=_Part_892_1937190326.1533919291831
Content-Type: multipart/alternative;
boundary="----=_Part_893_149707974.1533919291833"
------=_Part_893_149707974.1533919291833
Content-Type: text/plain; charset="UTF-8"
I was playing with memory allocations, what it is possible to do and how it
is implemented.
It made me think about relocations, so here is the result of my reflection.
"Relocation" definition:
An object is relocated when its address changes.
This does not necessarily implies a copy of its bytes.
When it can occur:
This could happen if a call to realloc is performed.
This could also happen as a compiler optimization.
How it can be integrated to the language:
Relocation cannot be a constructor: no new object is created.
Relocation cannot be an assignment operator: Only one object is involved.
So here is what I propose:
Every type has a relocation operator that takes a pointer and returning void
(let's call it operator relocate to ease the explanation, but I have no
strong opinion on the syntax).
This operator is called just after the object address has changed (for
whatever reason), and the pointer argument represents the old address of
the object (which is now an invalid address).
This operator can be deleted or defaulted.
The operator relocate is trivial iif:
- it is not user-provided (that is, it is implicitly-defined or
defaulted)
- T has no virtual member functions
- T has no virtual base classes
- the operator relocate selected for every direct base of T is trivial
- the operator relocate selected for every non-static class type (or
array of class type) member of T is trivial
A trivial operator relocate is basically a noop.
No syntax is proposed to call relocation (apart from object.operator
relocate(p)).
An operator relocate shall not change the state of the object if the new
address is the same as the old address, even if the operator is not trivial.
It also cannot be virtual (you shall relocate only object through their
true type).
I propose that throwing relocation is allowed, but discouraged (but if this
is problematic, I see no strong reason to keep throwing relocation).
Small example:
struct Bar;
struct Foo {
Bar* bar;
};
struct Bar {
Foo* foo; // foo.bar is always equals to this
Bar() : foo(new Foo{this}) {}
~Bar() {
delete foo;
}
// copy is deleted
Bar(const Bar&) = delete;
Bar& operator=(const Bar&) = delete;
// move needs to set the foo.bar to this object
Bar(Bar&& other) : foo(other.foo) {
other.foo = nullptr;
foo.bar = this;
}
Bar& operator=(Bar&& other) {
swap(foo, other.foo);
foo.bar = this;
other.foo.bar = &other;
return *this;
}
// If address has changed, reset the foo.bar to point to the new location
of the object
void operator relocate(void*) {
foo.bar = this;
}
};
Is relocation the same as move?
No: move is creating a new object from an expiring object.
The expiring object might be used afterwards (eg: std::swap).
With relocation, there is a single object whose address changes.
Is relocation the same as destructive move?
No: destructive move means there is a storage for both old and new objects
at the same time, and the object is copied from the old storage to the new
storage with the assumption that the old storage does not contain any
living object after the move and the new storage does not contain any
living object before the move. (destructive move is not part of the
language yet)
Relocation involves a single storage, whose address has changed.
This can happen without any byte being copied (eg: mremap).
Though, a destructive move can be implemented as memcpy + relocate for any
relocatable object (not only trivial ones).
When is relocation called?
Relocation might be called explicitly by user code, or directly by the
compiler as an optimization.
I don't propose any situation where the language guarantees a relocation
will happen.
I propose to allow the compiler to do (memcpy +) relocation instead of move
+ destruct without giving any guarantee.
The STL containers would need to be modified to take advantage of
relocation.
What are the advantages of relocation?
Most advantages are better optimizations.
An obvious optimization that most people try to achieve with destructive
moves is to be able to memcpy a buffer of objects into a larger buffer (for
instance in std::vector<std::unique_ptr<T>>).
Regular moves cannot do that.
Another one is the possibility to have "moveable" objects without the need
to have an empty state.
Relocation would also enable some types to be relocated without throwing
while their move constructor can throw.
Another optimization that can be done with such a relocation (and is not
possible with any current form relocation/destructive move) is to be able
to std::realloc a buffer, and just fix the objects afterwards.
Most realloc implementations will not perform any copy if the buffer is
large enough (only page remapping).
This is why relocation needs to work on a single storage whose address has
changed.
This last point means that growing a vector can be made O(1) for any
trivially relocatable types (using std::realloc which is O(1) on most
implementations).
(this was the starting point of my thinking)
What types would be trivially relocatable without being neither trivially
copyable nor trivially movable:
Actually, many types would be trivially relocatable:
- std::unique_ptr
- std::shared_ptr
- std::string
- std::vector
- std::map (?)
- std::unordered_map (?)
- std::deque (?)
- ...
Considering current implementations, std::list will most likely not be
trivially relocatable but surely can be nothrow relocatable.
How does it relate to other proposals?
Destructive Move (N4034
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4034.pdf>):
N4034 is a form of destructive move, so cannot handle std::realloc.
Every feature of N4034 is covered by relocation.
Relocator: Efficiently moving objects (P0023r0)
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0023r0.pdf>:
P0023r0 is a form of destructive move, so cannot handle std::realloc.
Every feature of P0023r0 is covered by my proposed relocation.
Compared to N4034, P0023r0 mentions "in-place relocation" which would be
feature equivalent to my proposed relocation.
P0023r0 also proposes a usable syntax to define relocators that can call
subobjects relocators which is similar to a constructor (yet is different).
[[move_relocates]] (P1029r0):
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1029r0.pdf>
P1029r0 is not about the general concept of relocation, but only about
trivial relocation.
P1029r0 proposes an attribute to decorate a move constructor to let the
compiler know a type is trivially relocatable.
[[move_relocates]] would be equivalent to trivially relocatable types.
The rules for implicit operator relocate would lead to most types being
automatically trivially relocatable without any code change.
Zero-overhead deterministic exceptions: Throwing values (P0709r1
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r1.pdf>):
That proposal is not about relocation nor destructive move whatsoever.
P0709r1 explicitly mandates that std::error must be trivially destructive
movable (which is designated by the term "trivially relocatable").
That proposal could then take advantage of the relocation I propose.
Low level le i/o library (P1031R1
<https://docs.google.com/viewer?a=v&pid=forums&srcid=MTEwODAzNzI2MjM1OTc0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQUFKATAuMQFpc29jcHAub3JnAXYy&authuser=0>
):
That proposal is not about relocation nor destructive move whatsoever.
"persistify + unpersistify" an object in a mapped memory region can be seen
as a relocation.
That proposal could benefit from my relocation proposal, especially
trivially relocatable types.
However, operator relocate takes the old address as argument. This address
would not be accessible when blessing the new object from the storage.
This could be solved by allowing the operator relocate to not take any
address.
Or we could introduce a pair of methods taking no argument:
delocate()/relocate().
The meaning would be: delocate() + address change + relocate() would be
equivalent to address change + relocate(void*)
We can discuss those possibilities directly on the thread of that proposal
<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/bk8esqk-Qoo>
Open questions
- What should be the syntax to define/call relocation?
- Is taking the old address as argument really needed?
- Would a 2 step relocation make more sense?
- Could relocation throw?
- Should a non-copyable, non movavble type be implicitly relocatable?
I hope you will find this proposal interesting, and I would be pleased to
answer any question about it.
Florian
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org.
------=_Part_893_149707974.1533919291833
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I was playing with memory allocations, what it is possible=
to do and how it is implemented.<br>It made me think about relocations, so=
here is the result of my reflection.<br><br><br><font size=3D"4">"Rel=
ocation" definition:</font><br><div style=3D"margin-left: 40px;">An ob=
ject is relocated when its address changes.<br>This does not necessarily im=
plies a copy of its bytes.<br></div><br><br><font size=3D"4">When it can oc=
cur:</font><br><div style=3D"margin-left: 40px;">This could happen if a cal=
l to realloc is performed.<br>This could also happen as a compiler optimiza=
tion.<br></div><br><br><font size=3D"4">How it can be integrated to the lan=
guage:</font><br><div style=3D"margin-left: 40px;">Relocation cannot be a c=
onstructor: no new object is created.<br>Relocation cannot be an assignment=
operator: Only one object is involved.<br><br>So here is what I propose:<b=
r>Every type has a relocation operator that takes a pointer and returning <=
span style=3D"font-family: courier new, monospace;">void</span> (let's =
call it <span style=3D"font-family: courier new, monospace;">operator reloc=
ate</span> to ease the explanation, but I have no strong opinion on the syn=
tax).<br>This operator is called just after the object address has changed =
(for whatever reason), and the pointer argument represents the old address =
of the object (which is now an invalid address).<br><br>This operator can b=
e deleted or defaulted.<br>The <span style=3D"font-family: courier new, mon=
ospace;">operator relocate</span> is trivial iif:</div><ul style=3D"margin-=
left: 40px;"><li> it is not user-provided (that is, it is implicitly-define=
d or defaulted)<span class=3D"t-rev-inl t-until-cxx14"><span></span></span>=
</li><li> <code>T</code> has no virtual member functions
</li><li> <code>T</code> has no virtual base classes
</li><li> the <span style=3D"font-family: courier new, monospace;">operator=
relocate</span> selected for every direct base of <code>T</code> is trivia=
l
</li><li> the <span style=3D"font-family: courier new, monospace;">operator=
relocate</span> selected for every non-static class type (or array of clas=
s type) member of <code>T</code> is trivial
</li></ul><p style=3D"margin-left: 40px;">A trivial <span style=3D"font-fam=
ily: courier new, monospace;">operator relocate</span> is basically a noop.=
<br></p><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40=
px;">No syntax is proposed to call relocation (apart from <span style=3D"fo=
nt-family: courier new, monospace;">object.operator relocate(p)</span>).</p=
><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px;">An=
<span style=3D"font-family: courier new, monospace;">operator relocate</sp=
an> shall not change the state of the object if the new address is the same=
as the old address, even if the operator is not trivial.</p><p style=3D"ma=
rgin-left: 40px;">It also cannot be virtual (you shall relocate only object=
through their true type).<br></p><p style=3D"margin-left: 40px;"><br></p><=
p style=3D"margin-left: 40px;">I propose that throwing relocation is allowe=
d, but discouraged (but if this is problematic, I see no strong reason to k=
eep throwing relocation).</p><p><br></p><p><font size=3D"4">Small example:<=
/font></p><p style=3D"margin-left: 40px;"></p><div style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color=
: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Bar</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> bar</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
<br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Bar</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #606=
;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> // foo.bar is always equals to this<br><br>=C2=A0 </span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">})</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">~</span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Bar</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">delete</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span></code><br>=C2=A0 // copy is de=
leted<br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">delete</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled=
-by-prettify">Bar</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">operato=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D(</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&)</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">delete</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r><br>=C2=A0 // move needs to set the foo.bar to this object<br></span></co=
de>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Bar</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&&</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> other</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">other</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">foo</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 other</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">foo </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">nullptr</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">bar </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">operator</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D(</span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Bar</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&&</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> other</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 swap</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">foo</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> other</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">foo</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">bar </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 other</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">foo</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">bar </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">other</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br>=C2=A0 // If address has changed,=
reset the foo.bar to point to the new location of the object<br>=C2=A0 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> relocate</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">*)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">bar </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span></div></code></div><p></p><p><br></p><p=
><br></p><p><font size=3D"4">Is relocation the same as move?</font></p><p s=
tyle=3D"margin-left: 40px;">No: move is creating a new object from an expir=
ing object.</p><p style=3D"margin-left: 40px;">The expiring object might be=
used afterwards (eg: std::swap).</p><p style=3D"margin-left: 40px;"><br></=
p><p style=3D"margin-left: 40px;">With relocation, there is a single object=
whose address changes.</p><p><br></p><p><font size=3D"4">Is relocation the=
same as destructive move?</font></p><p style=3D"margin-left: 40px;">No: de=
structive move means there is a storage for both old and new objects at the=
same time, and the object is copied from the old storage to the new storag=
e with the assumption that the old storage does not contain any living obje=
ct after the move and the new storage does not contain any living object be=
fore the move. (destructive move is not part of the language yet)<br></p><p=
style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px;">Reloc=
ation involves a single storage, whose address has changed.</p><p style=3D"=
margin-left: 40px;">This can happen without any byte being copied (eg: mrem=
ap).</p><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40=
px;">Though, a destructive move can be implemented as memcpy + relocate for=
any relocatable object (not only trivial ones).</p><p><br></p><p><font siz=
e=3D"4">When is relocation called?</font></p><p style=3D"margin-left: 40px;=
">Relocation might be called explicitly by user code, or directly by the co=
mpiler as an optimization.</p><p style=3D"margin-left: 40px;"><br></p><p st=
yle=3D"margin-left: 40px;">I don't propose any situation where the lang=
uage guarantees a relocation will happen.</p><p style=3D"margin-left: 40px;=
">I propose to allow the compiler to do (memcpy +) relocation instead of mo=
ve + destruct without giving any guarantee.</p><p style=3D"margin-left: 40p=
x;">The STL containers would need to be modified to take advantage of reloc=
ation.</p><p><br></p><p><font size=3D"4">What are the advantages of relocat=
ion?</font></p><p style=3D"margin-left: 40px;">Most advantages are better o=
ptimizations.</p><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin=
-left: 40px;">An obvious optimization that most people try to achieve with =
destructive moves is to be able to memcpy a buffer of objects into a larger=
buffer (for instance in std::vector<std::unique_ptr<T>>).</p><=
p style=3D"margin-left: 40px;">Regular moves cannot do that.</p><p style=3D=
"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px;">Another one is=
the possibility to have "moveable" objects without the need to h=
ave an empty state.</p><p style=3D"margin-left: 40px;"><br></p><p style=3D"=
margin-left: 40px;">Relocation would also enable some types to be relocated=
without throwing while their move constructor can throw.<br></p><p style=
=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px;">Another opt=
imization that can be done with such a relocation (and is not possible with=
any current form relocation/destructive move) is to be able to <span style=
=3D"font-family: courier new, monospace;">std::realloc</span> a buffer, and=
just fix the objects afterwards.</p><p style=3D"margin-left: 40px;">Most r=
ealloc implementations will not perform any copy if the buffer is large eno=
ugh (only page remapping).</p><p style=3D"margin-left: 40px;">This is why r=
elocation needs to work on a single storage whose address has changed.<br><=
/p><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px;">=
This last point means that growing a vector can be made O(1) for any trivia=
lly relocatable types (using <span style=3D"font-family: courier new, monos=
pace;">std::realloc</span> which is O(1) on most implementations).</p><p st=
yle=3D"margin-left: 40px;">(this was the starting point of my thinking)<br>=
</p><p><br></p><p><br></p><p><font size=3D"4">What types would be trivially=
relocatable without being neither trivially copyable nor trivially movable=
:</font><br></p><p style=3D"margin-left: 40px;">Actually, many types would =
be trivially relocatable:</p><ul style=3D"margin-left: 40px;"><li>std::uniq=
ue_ptr</li><li>std::shared_ptr</li><li>std::string</li><li>std::vector</li>=
<li>std::map (?)</li><li>std::unordered_map (?)</li><li>std::deque (?)</li>=
<li>...<br></li></ul><p style=3D"margin-left: 40px;"><br></p><p style=3D"ma=
rgin-left: 40px;">Considering current implementations, std::list will most =
likely not be trivially relocatable but surely can be nothrow relocatable.<=
/p><p><br></p><p><font size=3D"4">How does it relate to other proposals?</f=
ont></p><p><br></p><p>Destructive Move <a href=3D"http://www.open-std.org/j=
tc1/sc22/wg21/docs/papers/2014/n4034.pdf">(N4034</a>):</p><p style=3D"margi=
n-left: 40px;">N4034 is a form of destructive move, so cannot handle <span =
style=3D"font-family: courier new, monospace;">std::realloc</span>.</p><p s=
tyle=3D"margin-left: 40px;">Every feature of N4034 is covered by relocation=
..</p><p><br></p><p>Relocator: Efficiently moving objects (<a href=3D"http:/=
/www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0023r0.pdf">P0023r0)</a>=
:</p><p style=3D"margin-left: 40px;">P0023r0 is a form of destructive move,=
so cannot handle <span style=3D"font-family: courier new, monospace;">std:=
:realloc</span>.</p><p style=3D"margin-left: 40px;">Every feature of P0023r=
0 is covered by my proposed relocation.</p><p style=3D"margin-left: 40px;">=
<br></p><p style=3D"margin-left: 40px;">Compared to N4034, P0023r0 mentions=
"in-place relocation" which would be feature equivalent to my pr=
oposed relocation.</p><p style=3D"margin-left: 40px;">P0023r0 also proposes=
a usable syntax to define relocators that can call subobjects relocators w=
hich is similar to a constructor (yet is different).<br></p><p><br></p><p>[=
[move_relocates]] (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/p=
apers/2018/p1029r0.pdf">P1029r0):</a><br></p><p style=3D"margin-left: 40px;=
">P1029r0 is not about the general concept of relocation, but only about tr=
ivial relocation.</p><p style=3D"margin-left: 40px;">P1029r0 proposes an at=
tribute to decorate a move constructor to let the compiler know a type is t=
rivially relocatable.</p><p style=3D"margin-left: 40px;"><br></p><p style=
=3D"margin-left: 40px;">[[move_relocates]] would be equivalent to trivially=
relocatable types.</p><p style=3D"margin-left: 40px;">The rules for implic=
it <span style=3D"font-family: courier new, monospace;">operator relocate</=
span> would lead to most types being automatically trivially relocatable wi=
thout any code change.<br></p><p style=3D"margin-left: 40px;"><br></p><p>Ze=
ro-overhead deterministic exceptions: Throwing values (<a href=3D"http://ww=
w.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r1.pdf">P0709r1</a>):</=
p><p style=3D"margin-left: 40px;">That proposal is not about relocation nor=
destructive move whatsoever.</p><p style=3D"margin-left: 40px;">P0709r1 ex=
plicitly mandates that std::error must be trivially destructive movable (wh=
ich is designated by the term "trivially relocatable").</p><p sty=
le=3D"margin-left: 40px;">That proposal could then take advantage of the re=
location I propose.<br></p><p><br></p><p><br></p><p>Low level le i/o librar=
y (<a href=3D"https://docs.google.com/viewer?a=3Dv&pid=3Dforums&src=
id=3DMTEwODAzNzI2MjM1OTc0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQU=
FKATAuMQFpc29jcHAub3JnAXYy&authuser=3D0">P1031R1</a>):</p><p style=3D"m=
argin-left: 40px;">That proposal is not about relocation nor destructive mo=
ve whatsoever.</p><p style=3D"margin-left: 40px;">"persistify + unpers=
istify" an object in a mapped memory region can be seen as a relocatio=
n.</p><p style=3D"margin-left: 40px;"><br></p><p style=3D"margin-left: 40px=
;">That proposal could benefit from my relocation proposal, especially triv=
ially relocatable types.</p><p style=3D"margin-left: 40px;">However, operat=
or relocate takes the old address as argument. This address would not be ac=
cessible when blessing the new object from the storage.</p><p style=3D"marg=
in-left: 40px;">This could be solved by allowing the operator relocate to n=
ot take any address.</p><p style=3D"margin-left: 40px;"><br></p><p style=3D=
"margin-left: 40px;">Or we could introduce a pair of methods taking no argu=
ment: <span style=3D"font-family: courier new, monospace;">delocate()/reloc=
ate()</span>.</p><p style=3D"margin-left: 40px;">The meaning would be: <spa=
n style=3D"font-family: courier new, monospace;">delocate() + address chang=
e + relocate()</span> would be equivalent to <span style=3D"font-family: co=
urier new, monospace;">address change + relocate(void*)</span></p><p style=
=3D"margin-left: 40px;">We can discuss those possibilities directly on the =
<a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposa=
ls/bk8esqk-Qoo">thread of that proposal</a></p><p><br></p><p><font size=3D"=
4">Open questions</font></p><ul><li>What should be the syntax to define/cal=
l relocation?</li><li>Is taking the old address as argument really needed?<=
/li><li>Would a 2 step relocation make more sense?</li><li>Could relocation=
throw?</li><li>Should a non-copyable, non movavble type be implicitly relo=
catable?<br></li></ul><br><br><br>I hope you will find this proposal intere=
sting, and I would be pleased to answer any question about it.<br><br>Flori=
an<br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab=
%40isocpp.org</a>.<br />
------=_Part_893_149707974.1533919291833--
------=_Part_892_1937190326.1533919291831--
.
Author: Nicolas Lesser <blitzrakete@gmail.com>
Date: Fri, 10 Aug 2018 10:04:48 -0700
Raw View
--0000000000006ddeba057317c99a
Content-Type: text/plain; charset="UTF-8"
I can't tell whether you are aware of the "Trivially Relocatable" proposal.
Here's a blog post on it with a draft paper:
https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/
It's a bit like P1029 though, but it addresses the one concern that you
have for P1029.
On Fri, Aug 10, 2018 at 9:41 AM <florian.csdt@gmail.com> wrote:
> I was playing with memory allocations, what it is possible to do and how
> it is implemented.
> It made me think about relocations, so here is the result of my reflection.
>
>
> "Relocation" definition:
> An object is relocated when its address changes.
> This does not necessarily implies a copy of its bytes.
>
>
> When it can occur:
> This could happen if a call to realloc is performed.
> This could also happen as a compiler optimization.
>
>
> How it can be integrated to the language:
> Relocation cannot be a constructor: no new object is created.
> Relocation cannot be an assignment operator: Only one object is involved.
>
> So here is what I propose:
> Every type has a relocation operator that takes a pointer and returning
> void (let's call it operator relocate to ease the explanation, but I have
> no strong opinion on the syntax).
> This operator is called just after the object address has changed (for
> whatever reason), and the pointer argument represents the old address of
> the object (which is now an invalid address).
>
> This operator can be deleted or defaulted.
> The operator relocate is trivial iif:
>
> - it is not user-provided (that is, it is implicitly-defined or
> defaulted)
> - T has no virtual member functions
> - T has no virtual base classes
> - the operator relocate selected for every direct base of T is trivial
> - the operator relocate selected for every non-static class type (or
> array of class type) member of T is trivial
>
> A trivial operator relocate is basically a noop.
>
>
> No syntax is proposed to call relocation (apart from object.operator
> relocate(p)).
>
>
> An operator relocate shall not change the state of the object if the new
> address is the same as the old address, even if the operator is not trivial.
>
> It also cannot be virtual (you shall relocate only object through their
> true type).
>
>
> I propose that throwing relocation is allowed, but discouraged (but if
> this is problematic, I see no strong reason to keep throwing relocation).
>
>
> Small example:
>
> struct Bar;
> struct Foo {
> Bar* bar;
> };
>
> struct Bar {
> Foo* foo; // foo.bar is always equals to this
>
> Bar() : foo(new Foo{this}) {}
> ~Bar() {
> delete foo;
> }
>
> // copy is deleted
> Bar(const Bar&) = delete;
> Bar& operator=(const Bar&) = delete;
>
> // move needs to set the foo.bar to this object
> Bar(Bar&& other) : foo(other.foo) {
> other.foo = nullptr;
> foo.bar = this;
> }
> Bar& operator=(Bar&& other) {
> swap(foo, other.foo);
> foo.bar = this;
> other.foo.bar = &other;
> return *this;
> }
>
> // If address has changed, reset the foo.bar to point to the new
> location of the object
> void operator relocate(void*) {
> foo.bar = this;
> }
> };
>
>
>
> Is relocation the same as move?
>
> No: move is creating a new object from an expiring object.
>
> The expiring object might be used afterwards (eg: std::swap).
>
>
> With relocation, there is a single object whose address changes.
>
>
> Is relocation the same as destructive move?
>
> No: destructive move means there is a storage for both old and new objects
> at the same time, and the object is copied from the old storage to the new
> storage with the assumption that the old storage does not contain any
> living object after the move and the new storage does not contain any
> living object before the move. (destructive move is not part of the
> language yet)
>
>
> Relocation involves a single storage, whose address has changed.
>
> This can happen without any byte being copied (eg: mremap).
>
>
> Though, a destructive move can be implemented as memcpy + relocate for any
> relocatable object (not only trivial ones).
>
>
> When is relocation called?
>
> Relocation might be called explicitly by user code, or directly by the
> compiler as an optimization.
>
>
> I don't propose any situation where the language guarantees a relocation
> will happen.
>
> I propose to allow the compiler to do (memcpy +) relocation instead of
> move + destruct without giving any guarantee.
>
> The STL containers would need to be modified to take advantage of
> relocation.
>
>
> What are the advantages of relocation?
>
> Most advantages are better optimizations.
>
>
> An obvious optimization that most people try to achieve with destructive
> moves is to be able to memcpy a buffer of objects into a larger buffer (for
> instance in std::vector<std::unique_ptr<T>>).
>
> Regular moves cannot do that.
>
>
> Another one is the possibility to have "moveable" objects without the need
> to have an empty state.
>
>
> Relocation would also enable some types to be relocated without throwing
> while their move constructor can throw.
>
>
> Another optimization that can be done with such a relocation (and is not
> possible with any current form relocation/destructive move) is to be able
> to std::realloc a buffer, and just fix the objects afterwards.
>
> Most realloc implementations will not perform any copy if the buffer is
> large enough (only page remapping).
>
> This is why relocation needs to work on a single storage whose address has
> changed.
>
>
> This last point means that growing a vector can be made O(1) for any
> trivially relocatable types (using std::realloc which is O(1) on most
> implementations).
>
> (this was the starting point of my thinking)
>
>
>
> What types would be trivially relocatable without being neither trivially
> copyable nor trivially movable:
>
> Actually, many types would be trivially relocatable:
>
> - std::unique_ptr
> - std::shared_ptr
> - std::string
> - std::vector
> - std::map (?)
> - std::unordered_map (?)
> - std::deque (?)
> - ...
>
>
> Considering current implementations, std::list will most likely not be
> trivially relocatable but surely can be nothrow relocatable.
>
>
> How does it relate to other proposals?
>
>
> Destructive Move (N4034
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4034.pdf>):
>
> N4034 is a form of destructive move, so cannot handle std::realloc.
>
> Every feature of N4034 is covered by relocation.
>
>
> Relocator: Efficiently moving objects (P0023r0)
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0023r0.pdf>:
>
> P0023r0 is a form of destructive move, so cannot handle std::realloc.
>
> Every feature of P0023r0 is covered by my proposed relocation.
>
>
> Compared to N4034, P0023r0 mentions "in-place relocation" which would be
> feature equivalent to my proposed relocation.
>
> P0023r0 also proposes a usable syntax to define relocators that can call
> subobjects relocators which is similar to a constructor (yet is different).
>
>
> [[move_relocates]] (P1029r0):
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1029r0.pdf>
>
> P1029r0 is not about the general concept of relocation, but only about
> trivial relocation.
>
> P1029r0 proposes an attribute to decorate a move constructor to let the
> compiler know a type is trivially relocatable.
>
>
> [[move_relocates]] would be equivalent to trivially relocatable types.
>
> The rules for implicit operator relocate would lead to most types being
> automatically trivially relocatable without any code change.
>
>
> Zero-overhead deterministic exceptions: Throwing values (P0709r1
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r1.pdf>):
>
> That proposal is not about relocation nor destructive move whatsoever.
>
> P0709r1 explicitly mandates that std::error must be trivially destructive
> movable (which is designated by the term "trivially relocatable").
>
> That proposal could then take advantage of the relocation I propose.
>
>
>
> Low level le i/o library (P1031R1
> <https://docs.google.com/viewer?a=v&pid=forums&srcid=MTEwODAzNzI2MjM1OTc0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQUFKATAuMQFpc29jcHAub3JnAXYy&authuser=0>
> ):
>
> That proposal is not about relocation nor destructive move whatsoever.
>
> "persistify + unpersistify" an object in a mapped memory region can be
> seen as a relocation.
>
>
> That proposal could benefit from my relocation proposal, especially
> trivially relocatable types.
>
> However, operator relocate takes the old address as argument. This address
> would not be accessible when blessing the new object from the storage.
>
> This could be solved by allowing the operator relocate to not take any
> address.
>
>
> Or we could introduce a pair of methods taking no argument:
> delocate()/relocate().
>
> The meaning would be: delocate() + address change + relocate() would be
> equivalent to address change + relocate(void*)
>
> We can discuss those possibilities directly on the thread of that proposal
> <https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/bk8esqk-Qoo>
>
>
> Open questions
>
> - What should be the syntax to define/call relocation?
> - Is taking the old address as argument really needed?
> - Would a 2 step relocation make more sense?
> - Could relocation throw?
> - Should a non-copyable, non movavble type be implicitly relocatable?
>
>
>
>
> I hope you will find this proposal interesting, and I would be pleased to
> answer any question about it.
>
> Florian
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1QY%3DU4C2L%2BSiQ6RFR%2BppQ38ZBMoEhNwzBEDi9MFOkkMg%40mail.gmail.com.
--0000000000006ddeba057317c99a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I can't tell whether you are aware of the "Trivia=
lly Relocatable" proposal. Here's a blog post on it with a draft p=
aper:=C2=A0<a href=3D"https://quuxplusone.github.io/blog/2018/07/18/announc=
ing-trivially-relocatable/">https://quuxplusone.github.io/blog/2018/07/18/a=
nnouncing-trivially-relocatable/</a>=C2=A0<div><br></div><div>It's a bi=
t like P1029 though, but it addresses the one concern that you have for P10=
29.</div></div><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, Aug =
10, 2018 at 9:41 AM <<a href=3D"mailto:florian.csdt@gmail.com">florian.c=
sdt@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr">I was playing with memory allocations, what it is possible to do=
and how it is implemented.<br>It made me think about relocations, so here =
is the result of my reflection.<br><br><br><font size=3D"4">"Relocatio=
n" definition:</font><br><div style=3D"margin-left:40px">An object is =
relocated when its address changes.<br>This does not necessarily implies a =
copy of its bytes.<br></div><br><br><font size=3D"4">When it can occur:</fo=
nt><br><div style=3D"margin-left:40px">This could happen if a call to reall=
oc is performed.<br>This could also happen as a compiler optimization.<br><=
/div><br><br><font size=3D"4">How it can be integrated to the language:</fo=
nt><br><div style=3D"margin-left:40px">Relocation cannot be a constructor: =
no new object is created.<br>Relocation cannot be an assignment operator: O=
nly one object is involved.<br><br>So here is what I propose:<br>Every type=
has a relocation operator that takes a pointer and returning <span style=
=3D"font-family:courier new,monospace">void</span> (let's call it <span=
style=3D"font-family:courier new,monospace">operator relocate</span> to ea=
se the explanation, but I have no strong opinion on the syntax).<br>This op=
erator is called just after the object address has changed (for whatever re=
ason), and the pointer argument represents the old address of the object (w=
hich is now an invalid address).<br><br>This operator can be deleted or def=
aulted.<br>The <span style=3D"font-family:courier new,monospace">operator r=
elocate</span> is trivial iif:</div><ul style=3D"margin-left:40px"><li> it =
is not user-provided (that is, it is implicitly-defined or defaulted)<span =
class=3D"m_3287405730556293944t-rev-inl m_3287405730556293944t-until-cxx14"=
><span></span></span></li><li> <code>T</code> has no virtual member functio=
ns
</li><li> <code>T</code> has no virtual base classes
</li><li> the <span style=3D"font-family:courier new,monospace">operator re=
locate</span> selected for every direct base of <code>T</code> is trivial
</li><li> the <span style=3D"font-family:courier new,monospace">operator re=
locate</span> selected for every non-static class type (or array of class t=
ype) member of <code>T</code> is trivial
</li></ul><p style=3D"margin-left:40px">A trivial <span style=3D"font-famil=
y:courier new,monospace">operator relocate</span> is basically a noop.<br><=
/p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">No s=
yntax is proposed to call relocation (apart from <span style=3D"font-family=
:courier new,monospace">object.operator relocate(p)</span>).</p><p style=3D=
"margin-left:40px"><br></p><p style=3D"margin-left:40px">An <span style=3D"=
font-family:courier new,monospace">operator relocate</span> shall not chang=
e the state of the object if the new address is the same as the old address=
, even if the operator is not trivial.</p><p style=3D"margin-left:40px">It =
also cannot be virtual (you shall relocate only object through their true t=
ype).<br></p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:=
40px">I propose that throwing relocation is allowed, but discouraged (but i=
f this is problematic, I see no strong reason to keep throwing relocation).=
</p><p><br></p><p><font size=3D"4">Small example:</font></p><p style=3D"mar=
gin-left:40px"></p><div style=3D"background-color:rgb(250,250,250);border-c=
olor:rgb(187,187,187);border-style:solid;border-width:1px" class=3D"m_32874=
05730556293944prettyprint"><code class=3D"m_3287405730556293944prettyprint"=
><div class=3D"m_3287405730556293944subprettyprint"><span style=3D"color:#0=
08" class=3D"m_3287405730556293944styled-by-prettify">struct</span><span st=
yle=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </spa=
n><span style=3D"color:#606" class=3D"m_3287405730556293944styled-by-pretti=
fy">Bar</span><span style=3D"color:#660" class=3D"m_3287405730556293944styl=
ed-by-prettify">;</span><span style=3D"color:#000" class=3D"m_3287405730556=
293944styled-by-prettify"><br></span><span style=3D"color:#008" class=3D"m_=
3287405730556293944styled-by-prettify">struct</span><span style=3D"color:#0=
00" class=3D"m_3287405730556293944styled-by-prettify"> </span><span style=
=3D"color:#606" class=3D"m_3287405730556293944styled-by-prettify">Foo</span=
><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettif=
y"> </span><span style=3D"color:#660" class=3D"m_3287405730556293944styled-=
by-prettify">{</span><span style=3D"color:#000" class=3D"m_3287405730556293=
944styled-by-prettify"><br>=C2=A0 </span><span style=3D"color:#606" class=
=3D"m_3287405730556293944styled-by-prettify">Bar</span><span style=3D"color=
:#660" class=3D"m_3287405730556293944styled-by-prettify">*</span><span styl=
e=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> bar</sp=
an><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prett=
ify">;</span><span style=3D"color:#000" class=3D"m_3287405730556293944style=
d-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_32874057305=
56293944styled-by-prettify">};</span><span style=3D"color:#000" class=3D"m_=
3287405730556293944styled-by-prettify"><br><br></span><span style=3D"color:=
#008" class=3D"m_3287405730556293944styled-by-prettify">struct</span><span =
style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </s=
pan><span style=3D"color:#606" class=3D"m_3287405730556293944styled-by-pret=
tify">Bar</span><span style=3D"color:#000" class=3D"m_3287405730556293944st=
yled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_32874057305=
56293944styled-by-prettify">{</span><span style=3D"color:#000" class=3D"m_3=
287405730556293944styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r:#606" class=3D"m_3287405730556293944styled-by-prettify">Foo</span><span s=
tyle=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">*</sp=
an><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prett=
ify"> foo</span><span style=3D"color:#660" class=3D"m_3287405730556293944st=
yled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_32874057305=
56293944styled-by-prettify"> // foo.bar is always equals to this<br><br>=C2=
=A0 </span><span style=3D"color:#606" class=3D"m_3287405730556293944styled-=
by-prettify">Bar</span><span style=3D"color:#660" class=3D"m_32874057305562=
93944styled-by-prettify">()</span><span style=3D"color:#000" class=3D"m_328=
7405730556293944styled-by-prettify"> </span><span style=3D"color:#660" clas=
s=3D"m_3287405730556293944styled-by-prettify">:</span><span style=3D"color:=
#000" class=3D"m_3287405730556293944styled-by-prettify"> foo</span><span st=
yle=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">(</spa=
n><span style=3D"color:#008" class=3D"m_3287405730556293944styled-by-pretti=
fy">new</span><span style=3D"color:#000" class=3D"m_3287405730556293944styl=
ed-by-prettify"> </span><span style=3D"color:#606" class=3D"m_3287405730556=
293944styled-by-prettify">Foo</span><span style=3D"color:#660" class=3D"m_3=
287405730556293944styled-by-prettify">{</span><span style=3D"color:#008" cl=
ass=3D"m_3287405730556293944styled-by-prettify">this</span><span style=3D"c=
olor:#660" class=3D"m_3287405730556293944styled-by-prettify">})</span><span=
style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </=
span><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-pre=
ttify">{}</span><span style=3D"color:#000" class=3D"m_3287405730556293944st=
yled-by-prettify"><code class=3D"m_3287405730556293944prettyprint"><span st=
yle=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color:#660" class=3D"m_3287405730556293944styl=
ed-by-prettify">~</span><span style=3D"color:#606" class=3D"m_3287405730556=
293944styled-by-prettify">Bar</span><span style=3D"color:#660" class=3D"m_3=
287405730556293944styled-by-prettify">()</span><span style=3D"color:#000" c=
lass=3D"m_3287405730556293944styled-by-prettify"> </span><span style=3D"col=
or:#660" class=3D"m_3287405730556293944styled-by-prettify">{</span><span st=
yle=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_3287405730556293=
944styled-by-prettify">delete</span><span style=3D"color:#000" class=3D"m_3=
287405730556293944styled-by-prettify"> foo</span><span style=3D"color:#660"=
class=3D"m_3287405730556293944styled-by-prettify">;</span><span style=3D"c=
olor:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=C2=A0 </s=
pan><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-pret=
tify">}</span><span style=3D"color:#000" class=3D"m_3287405730556293944styl=
ed-by-prettify"><br></span></code><br>=C2=A0 // copy is deleted<br>=C2=A0 <=
/span><span style=3D"color:#606" class=3D"m_3287405730556293944styled-by-pr=
ettify">Bar</span><span style=3D"color:#660" class=3D"m_3287405730556293944=
styled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_328740573=
0556293944styled-by-prettify">const</span><span style=3D"color:#000" class=
=3D"m_3287405730556293944styled-by-prettify"> </span><span style=3D"color:#=
606" class=3D"m_3287405730556293944styled-by-prettify">Bar</span><span styl=
e=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">&)</=
span><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-pre=
ttify"> </span><span style=3D"color:#660" class=3D"m_3287405730556293944sty=
led-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_3287405730=
556293944styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_=
3287405730556293944styled-by-prettify">delete</span><span style=3D"color:#6=
60" class=3D"m_3287405730556293944styled-by-prettify">;</span><span style=
=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><code cla=
ss=3D"m_3287405730556293944prettyprint"><span style=3D"color:#000" class=3D=
"m_3287405730556293944styled-by-prettify"><br>=C2=A0 </span><span style=3D"=
color:#606" class=3D"m_3287405730556293944styled-by-prettify">Bar</span><sp=
an style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">&=
amp;</span><span style=3D"color:#000" class=3D"m_3287405730556293944styled-=
by-prettify"> </span><span style=3D"color:#008" class=3D"m_3287405730556293=
944styled-by-prettify">operator</span><span style=3D"color:#660" class=3D"m=
_3287405730556293944styled-by-prettify">=3D(</span><span style=3D"color:#00=
8" class=3D"m_3287405730556293944styled-by-prettify">const</span><span styl=
e=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </span>=
<span style=3D"color:#606" class=3D"m_3287405730556293944styled-by-prettify=
">Bar</span><span style=3D"color:#660" class=3D"m_3287405730556293944styled=
-by-prettify">&)</span><span style=3D"color:#000" class=3D"m_3287405730=
556293944styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_=
3287405730556293944styled-by-prettify">=3D</span><span style=3D"color:#000"=
class=3D"m_3287405730556293944styled-by-prettify"> </span><span style=3D"c=
olor:#008" class=3D"m_3287405730556293944styled-by-prettify">delete</span><=
span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify"=
>;</span><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by=
-prettify"><br><br>=C2=A0 // move needs to set the foo.bar to this object<b=
r></span></code>=C2=A0 </span><span style=3D"color:#606" class=3D"m_3287405=
730556293944styled-by-prettify">Bar</span><span style=3D"color:#660" class=
=3D"m_3287405730556293944styled-by-prettify">(</span><span style=3D"color:#=
606" class=3D"m_3287405730556293944styled-by-prettify">Bar</span><span styl=
e=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">&&am=
p;</span><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by=
-prettify"> other</span><span style=3D"color:#660" class=3D"m_3287405730556=
293944styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_328=
7405730556293944styled-by-prettify"> </span><span style=3D"color:#660" clas=
s=3D"m_3287405730556293944styled-by-prettify">:</span><span style=3D"color:=
#000" class=3D"m_3287405730556293944styled-by-prettify"> foo</span><span st=
yle=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">(</spa=
n><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-pretti=
fy">other</span><span style=3D"color:#660" class=3D"m_3287405730556293944st=
yled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_32874057305=
56293944styled-by-prettify">foo</span><span style=3D"color:#660" class=3D"m=
_3287405730556293944styled-by-prettify">)</span><span style=3D"color:#000" =
class=3D"m_3287405730556293944styled-by-prettify"> </span><span style=3D"co=
lor:#660" class=3D"m_3287405730556293944styled-by-prettify">{</span><span s=
tyle=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=
=C2=A0 =C2=A0 other</span><span style=3D"color:#660" class=3D"m_32874057305=
56293944styled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_3=
287405730556293944styled-by-prettify">foo </span><span style=3D"color:#660"=
class=3D"m_3287405730556293944styled-by-prettify">=3D</span><span style=3D=
"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </span><spa=
n style=3D"color:#008" class=3D"m_3287405730556293944styled-by-prettify">nu=
llptr</span><span style=3D"color:#660" class=3D"m_3287405730556293944styled=
-by-prettify">;</span><span style=3D"color:#000" class=3D"m_328740573055629=
3944styled-by-prettify"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color:#6=
60" class=3D"m_3287405730556293944styled-by-prettify">.</span><span style=
=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify">bar </spa=
n><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-pretti=
fy">=3D</span><span style=3D"color:#000" class=3D"m_3287405730556293944styl=
ed-by-prettify"> </span><span style=3D"color:#008" class=3D"m_3287405730556=
293944styled-by-prettify">this</span><span style=3D"color:#660" class=3D"m_=
3287405730556293944styled-by-prettify">;</span><span style=3D"color:#000" c=
lass=3D"m_3287405730556293944styled-by-prettify"><br>=C2=A0 </span><span st=
yle=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">}</spa=
n><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-pretti=
fy"><br>=C2=A0 </span><span style=3D"color:#606" class=3D"m_328740573055629=
3944styled-by-prettify">Bar</span><span style=3D"color:#660" class=3D"m_328=
7405730556293944styled-by-prettify">&</span><span style=3D"color:#000" =
class=3D"m_3287405730556293944styled-by-prettify"> </span><span style=3D"co=
lor:#008" class=3D"m_3287405730556293944styled-by-prettify">operator</span>=
<span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify=
">=3D(</span><span style=3D"color:#606" class=3D"m_3287405730556293944style=
d-by-prettify">Bar</span><span style=3D"color:#660" class=3D"m_328740573055=
6293944styled-by-prettify">&&</span><span style=3D"color:#000" clas=
s=3D"m_3287405730556293944styled-by-prettify"> other</span><span style=3D"c=
olor:#660" class=3D"m_3287405730556293944styled-by-prettify">)</span><span =
style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"> </s=
pan><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-pret=
tify">{</span><span style=3D"color:#000" class=3D"m_3287405730556293944styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 swap</span><span style=3D"color:#660" cla=
ss=3D"m_3287405730556293944styled-by-prettify">(</span><span style=3D"color=
:#000" class=3D"m_3287405730556293944styled-by-prettify">foo</span><span st=
yle=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">,</spa=
n><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-pretti=
fy"> other</span><span style=3D"color:#660" class=3D"m_3287405730556293944s=
tyled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_3287405730=
556293944styled-by-prettify">foo</span><span style=3D"color:#660" class=3D"=
m_3287405730556293944styled-by-prettify">);</span><span style=3D"color:#000=
" class=3D"m_3287405730556293944styled-by-prettify"><br>=C2=A0 =C2=A0 foo</=
span><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-pre=
ttify">.</span><span style=3D"color:#000" class=3D"m_3287405730556293944sty=
led-by-prettify">bar </span><span style=3D"color:#660" class=3D"m_328740573=
0556293944styled-by-prettify">=3D</span><span style=3D"color:#000" class=3D=
"m_3287405730556293944styled-by-prettify"> </span><span style=3D"color:#008=
" class=3D"m_3287405730556293944styled-by-prettify">this</span><span style=
=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">;</span><=
span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"=
><br>=C2=A0 =C2=A0 other</span><span style=3D"color:#660" class=3D"m_328740=
5730556293944styled-by-prettify">.</span><span style=3D"color:#000" class=
=3D"m_3287405730556293944styled-by-prettify">foo</span><span style=3D"color=
:#660" class=3D"m_3287405730556293944styled-by-prettify">.</span><span styl=
e=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify">bar </sp=
an><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prett=
ify">=3D</span><span style=3D"color:#000" class=3D"m_3287405730556293944sty=
led-by-prettify"> </span><span style=3D"color:#660" class=3D"m_328740573055=
6293944styled-by-prettify">&</span><span style=3D"color:#000" class=3D"=
m_3287405730556293944styled-by-prettify">other</span><span style=3D"color:#=
660" class=3D"m_3287405730556293944styled-by-prettify">;</span><span style=
=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_3287405730556293944=
styled-by-prettify">return</span><span style=3D"color:#000" class=3D"m_3287=
405730556293944styled-by-prettify"> </span><span style=3D"color:#660" class=
=3D"m_3287405730556293944styled-by-prettify">*</span><span style=3D"color:#=
008" class=3D"m_3287405730556293944styled-by-prettify">this</span><span sty=
le=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">;</span=
><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettif=
y"><br>=C2=A0 </span><span style=3D"color:#660" class=3D"m_3287405730556293=
944styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_328740=
5730556293944styled-by-prettify"><br><br>=C2=A0 // If address has changed, =
reset the foo.bar to point to the new location of the object<br>=C2=A0 </sp=
an><span style=3D"color:#008" class=3D"m_3287405730556293944styled-by-prett=
ify">void</span><span style=3D"color:#000" class=3D"m_3287405730556293944st=
yled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_32874057305=
56293944styled-by-prettify">operator</span><span style=3D"color:#000" class=
=3D"m_3287405730556293944styled-by-prettify"> relocate</span><span style=3D=
"color:#660" class=3D"m_3287405730556293944styled-by-prettify">(</span><spa=
n style=3D"color:#008" class=3D"m_3287405730556293944styled-by-prettify">vo=
id</span><span style=3D"color:#660" class=3D"m_3287405730556293944styled-by=
-prettify">*)</span><span style=3D"color:#000" class=3D"m_32874057305562939=
44styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_3287405=
730556293944styled-by-prettify">{</span><span style=3D"color:#000" class=3D=
"m_3287405730556293944styled-by-prettify"><br>=C2=A0 =C2=A0 foo</span><span=
style=3D"color:#660" class=3D"m_3287405730556293944styled-by-prettify">.</=
span><span style=3D"color:#000" class=3D"m_3287405730556293944styled-by-pre=
ttify">bar </span><span style=3D"color:#660" class=3D"m_3287405730556293944=
styled-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_3287405=
730556293944styled-by-prettify"> </span><span style=3D"color:#008" class=3D=
"m_3287405730556293944styled-by-prettify">this</span><span style=3D"color:#=
660" class=3D"m_3287405730556293944styled-by-prettify">;</span><span style=
=3D"color:#000" class=3D"m_3287405730556293944styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color:#660" class=3D"m_3287405730556293944styled-=
by-prettify">}</span><span style=3D"color:#000" class=3D"m_3287405730556293=
944styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_328=
7405730556293944styled-by-prettify">};</span><span style=3D"color:#000" cla=
ss=3D"m_3287405730556293944styled-by-prettify"><br></span></div></code></di=
v><p></p><p><br></p><p><br></p><p><font size=3D"4">Is relocation the same a=
s move?</font></p><p style=3D"margin-left:40px">No: move is creating a new =
object from an expiring object.</p><p style=3D"margin-left:40px">The expiri=
ng object might be used afterwards (eg: std::swap).</p><p style=3D"margin-l=
eft:40px"><br></p><p style=3D"margin-left:40px">With relocation, there is a=
single object whose address changes.</p><p><br></p><p><font size=3D"4">Is =
relocation the same as destructive move?</font></p><p style=3D"margin-left:=
40px">No: destructive move means there is a storage for both old and new ob=
jects at the same time, and the object is copied from the old storage to th=
e new storage with the assumption that the old storage does not contain any=
living object after the move and the new storage does not contain any livi=
ng object before the move. (destructive move is not part of the language ye=
t)<br></p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40p=
x">Relocation involves a single storage, whose address has changed.</p><p s=
tyle=3D"margin-left:40px">This can happen without any byte being copied (eg=
: mremap).</p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left=
:40px">Though, a destructive move can be implemented as memcpy + relocate f=
or any relocatable object (not only trivial ones).</p><p><br></p><p><font s=
ize=3D"4">When is relocation called?</font></p><p style=3D"margin-left:40px=
">Relocation might be called explicitly by user code, or directly by the co=
mpiler as an optimization.</p><p style=3D"margin-left:40px"><br></p><p styl=
e=3D"margin-left:40px">I don't propose any situation where the language=
guarantees a relocation will happen.</p><p style=3D"margin-left:40px">I pr=
opose to allow the compiler to do (memcpy +) relocation instead of move + d=
estruct without giving any guarantee.</p><p style=3D"margin-left:40px">The =
STL containers would need to be modified to take advantage of relocation.</=
p><p><br></p><p><font size=3D"4">What are the advantages of relocation?</fo=
nt></p><p style=3D"margin-left:40px">Most advantages are better optimizatio=
ns.</p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">=
An obvious optimization that most people try to achieve with destructive mo=
ves is to be able to memcpy a buffer of objects into a larger buffer (for i=
nstance in std::vector<std::unique_ptr<T>>).</p><p style=3D"mar=
gin-left:40px">Regular moves cannot do that.</p><p style=3D"margin-left:40p=
x"><br></p><p style=3D"margin-left:40px">Another one is the possibility to =
have "moveable" objects without the need to have an empty state.<=
/p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">Relo=
cation would also enable some types to be relocated without throwing while =
their move constructor can throw.<br></p><p style=3D"margin-left:40px"><br>=
</p><p style=3D"margin-left:40px">Another optimization that can be done wit=
h such a relocation (and is not possible with any current form relocation/d=
estructive move) is to be able to <span style=3D"font-family:courier new,mo=
nospace">std::realloc</span> a buffer, and just fix the objects afterwards.=
</p><p style=3D"margin-left:40px">Most realloc implementations will not per=
form any copy if the buffer is large enough (only page remapping).</p><p st=
yle=3D"margin-left:40px">This is why relocation needs to work on a single s=
torage whose address has changed.<br></p><p style=3D"margin-left:40px"><br>=
</p><p style=3D"margin-left:40px">This last point means that growing a vect=
or can be made O(1) for any trivially relocatable types (using <span style=
=3D"font-family:courier new,monospace">std::realloc</span> which is O(1) on=
most implementations).</p><p style=3D"margin-left:40px">(this was the star=
ting point of my thinking)<br></p><p><br></p><p><br></p><p><font size=3D"4"=
>What types would be trivially relocatable without being neither trivially =
copyable nor trivially movable:</font><br></p><p style=3D"margin-left:40px"=
>Actually, many types would be trivially relocatable:</p><ul style=3D"margi=
n-left:40px"><li>std::unique_ptr</li><li>std::shared_ptr</li><li>std::strin=
g</li><li>std::vector</li><li>std::map (?)</li><li>std::unordered_map (?)</=
li><li>std::deque (?)</li><li>...<br></li></ul><p style=3D"margin-left:40px=
"><br></p><p style=3D"margin-left:40px">Considering current implementations=
, std::list will most likely not be trivially relocatable but surely can be=
nothrow relocatable.</p><p><br></p><p><font size=3D"4">How does it relate =
to other proposals?</font></p><p><br></p><p>Destructive Move <a href=3D"htt=
p://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4034.pdf" target=3D"_=
blank">(N4034</a>):</p><p style=3D"margin-left:40px">N4034 is a form of des=
tructive move, so cannot handle <span style=3D"font-family:courier new,mono=
space">std::realloc</span>.</p><p style=3D"margin-left:40px">Every feature =
of N4034 is covered by relocation.</p><p><br></p><p>Relocator: Efficiently =
moving objects (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/pape=
rs/2016/p0023r0.pdf" target=3D"_blank">P0023r0)</a>:</p><p style=3D"margin-=
left:40px">P0023r0 is a form of destructive move, so cannot handle <span st=
yle=3D"font-family:courier new,monospace">std::realloc</span>.</p><p style=
=3D"margin-left:40px">Every feature of P0023r0 is covered by my proposed re=
location.</p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:=
40px">Compared to N4034, P0023r0 mentions "in-place relocation" w=
hich would be feature equivalent to my proposed relocation.</p><p style=3D"=
margin-left:40px">P0023r0 also proposes a usable syntax to define relocator=
s that can call subobjects relocators which is similar to a constructor (ye=
t is different).<br></p><p><br></p><p>[[move_relocates]] (<a href=3D"http:/=
/www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1029r0.pdf" target=3D"_b=
lank">P1029r0):</a><br></p><p style=3D"margin-left:40px">P1029r0 is not abo=
ut the general concept of relocation, but only about trivial relocation.</p=
><p style=3D"margin-left:40px">P1029r0 proposes an attribute to decorate a =
move constructor to let the compiler know a type is trivially relocatable.<=
/p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">[[mo=
ve_relocates]] would be equivalent to trivially relocatable types.</p><p st=
yle=3D"margin-left:40px">The rules for implicit <span style=3D"font-family:=
courier new,monospace">operator relocate</span> would lead to most types be=
ing automatically trivially relocatable without any code change.<br></p><p =
style=3D"margin-left:40px"><br></p><p>Zero-overhead deterministic exception=
s: Throwing values (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/=
papers/2018/p0709r1.pdf" target=3D"_blank">P0709r1</a>):</p><p style=3D"mar=
gin-left:40px">That proposal is not about relocation nor destructive move w=
hatsoever.</p><p style=3D"margin-left:40px">P0709r1 explicitly mandates tha=
t std::error must be trivially destructive movable (which is designated by =
the term "trivially relocatable").</p><p style=3D"margin-left:40p=
x">That proposal could then take advantage of the relocation I propose.<br>=
</p><p><br></p><p><br></p><p>Low level le i/o library (<a href=3D"https://d=
ocs.google.com/viewer?a=3Dv&pid=3Dforums&srcid=3DMTEwODAzNzI2MjM1OT=
c0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQUFKATAuMQFpc29jcHAub3JnA=
XYy&authuser=3D0" target=3D"_blank">P1031R1</a>):</p><p style=3D"margin=
-left:40px">That proposal is not about relocation nor destructive move what=
soever.</p><p style=3D"margin-left:40px">"persistify + unpersistify&qu=
ot; an object in a mapped memory region can be seen as a relocation.</p><p =
style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">That propo=
sal could benefit from my relocation proposal, especially trivially relocat=
able types.</p><p style=3D"margin-left:40px">However, operator relocate tak=
es the old address as argument. This address would not be accessible when b=
lessing the new object from the storage.</p><p style=3D"margin-left:40px">T=
his could be solved by allowing the operator relocate to not take any addre=
ss.</p><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">=
Or we could introduce a pair of methods taking no argument: <span style=3D"=
font-family:courier new,monospace">delocate()/relocate()</span>.</p><p styl=
e=3D"margin-left:40px">The meaning would be: <span style=3D"font-family:cou=
rier new,monospace">delocate() + address change + relocate()</span> would b=
e equivalent to <span style=3D"font-family:courier new,monospace">address c=
hange + relocate(void*)</span></p><p style=3D"margin-left:40px">We can disc=
uss those possibilities directly on the <a href=3D"https://groups.google.co=
m/a/isocpp.org/forum/#!topic/std-proposals/bk8esqk-Qoo" target=3D"_blank">t=
hread of that proposal</a></p><p><br></p><p><font size=3D"4">Open questions=
</font></p><ul><li>What should be the syntax to define/call relocation?</li=
><li>Is taking the old address as argument really needed?</li><li>Would a 2=
step relocation make more sense?</li><li>Could relocation throw?</li><li>S=
hould a non-copyable, non movavble type be implicitly relocatable?<br></li>=
</ul><br><br><br>I hope you will find this proposal interesting, and I woul=
d be pleased to answer any question about it.<br><br>Florian<br></div>
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-=
47a9-bb42-9e2ba06dccab%40isocpp.org</a>.<br>
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CALmDwq1QY%3DU4C2L%2BSiQ6RFR%2BppQ38Z=
BMoEhNwzBEDi9MFOkkMg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1QY%=
3DU4C2L%2BSiQ6RFR%2BppQ38ZBMoEhNwzBEDi9MFOkkMg%40mail.gmail.com</a>.<br />
--0000000000006ddeba057317c99a--
.
Author: florian.csdt@gmail.com
Date: Fri, 10 Aug 2018 10:19:01 -0700 (PDT)
Raw View
------=_Part_863_1761433725.1533921541339
Content-Type: multipart/alternative;
boundary="----=_Part_864_2073737726.1533921541340"
------=_Part_864_2073737726.1533921541340
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
No, I was not aware of this very proposal. (That's quite hard to keep track=
=20
of all proposals)
However, it also shares some issues with most other proposals.
Namely: it talks about destructive move (two different storages, moving the=
=20
actual object from one to the other).
Also, only trivial destructive moves are considered (no user defined).
But my proposal talks about in-place relocation: there is one single=20
storage whose address has changed.
And the relocation can be user-defined (a std::list could be made nothrow=
=20
relocatable).
Le vendredi 10 ao=C3=BBt 2018 19:08:06 UTC+2, Nicolas Lesser a =C3=A9crit :
>
> I can't tell whether you are aware of the "Trivially Relocatable"=20
> proposal. Here's a blog post on it with a draft paper:=20
> https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-reloca=
table/
> =20
>
> It's a bit like P1029 though, but it addresses the one concern that you=
=20
> have for P1029.
>
>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b5993c9e-8a5d-438f-ac8b-deec5641cb3e%40isocpp.or=
g.
------=_Part_864_2073737726.1533921541340
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">No, I was not aware of this very proposal. (That's qui=
te hard to keep track of all proposals)<br><br>However, it also shares some=
issues with most other proposals.<br>Namely: it talks about destructive mo=
ve (two different storages, moving the actual object from one to the other)=
..<br>Also, only trivial destructive moves are considered (no user defined).=
<br><br>But my proposal talks about in-place relocation: there is one singl=
e storage whose address has changed.<br>And the relocation can be user-defi=
ned (a std::list could be made nothrow relocatable).<br><br>Le vendredi 10 =
ao=C3=BBt 2018 19:08:06 UTC+2, Nicolas Lesser a =C3=A9crit=C2=A0:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I can't tell whethe=
r you are aware of the "Trivially Relocatable" proposal. Here'=
;s a blog post on it with a draft paper:=C2=A0<a href=3D"https://quuxpluson=
e.github.io/blog/2018/07/18/announcing-trivially-relocatable/" target=3D"_b=
lank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.c=
om/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.io%2Fblog%2F2018%2F07%2F18%2Fa=
nnouncing-trivially-relocatable%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
GEA9QMgWs5WBFLICjqL2WLBLKLIg';return true;" onclick=3D"this.href=3D'=
;https://www.google.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.io%2Fblog=
%2F2018%2F07%2F18%2Fannouncing-trivially-relocatable%2F\x26sa\x3dD\x26sntz\=
x3d1\x26usg\x3dAFQjCNGEA9QMgWs5WBFLICjqL2WLBLKLIg';return true;">https:=
//quuxplusone.<wbr>github.io/blog/2018/07/18/<wbr>announcing-trivially-<wbr=
>relocatable/</a>=C2=A0<div><br></div><div>It's a bit like P1029 though=
, but it addresses the one concern that you have for P1029.</div></div><br>=
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b5993c9e-8a5d-438f-ac8b-deec5641cb3e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b5993c9e-8a5d-438f-ac8b-deec5641cb3e=
%40isocpp.org</a>.<br />
------=_Part_864_2073737726.1533921541340--
------=_Part_863_1761433725.1533921541339--
.
Author: mihailnajdenov@gmail.com
Date: Fri, 10 Aug 2018 10:50:11 -0700 (PDT)
Raw View
------=_Part_866_27335325.1533923411384
Content-Type: multipart/alternative;
boundary="----=_Part_867_1791482099.1533923411384"
------=_Part_867_1791482099.1533923411384
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, August 10, 2018 at 8:19:01 PM UTC+3, floria...@gmail.com wrote:
>
> No, I was not aware of this very proposal. (That's quite hard to keep=20
> track of all proposals)
>
> However, it also shares some issues with most other proposals.
> Namely: it talks about destructive move (two different storages, moving=
=20
> the actual object from one to the other).
>
Destructive move handles self referential, this one does not (by design).
In that sense yours more like destructive then it :)
Anyway, the issue I see is the fact, it is not clear how it is communicated=
=20
by the language when it is to be called.
Because "when the address changes" is not a language category. What are=20
the rules, when should the compiler emit it.=20
=20
> Also, only trivial destructive moves are considered (no user defined).
>
> But my proposal talks about in-place relocation: there is one single=20
> storage whose address has changed.
> And the relocation can be user-defined (a std::list could be made nothrow=
=20
> relocatable).
>
> Le vendredi 10 ao=C3=BBt 2018 19:08:06 UTC+2, Nicolas Lesser a =C3=A9crit=
:
>>
>> I can't tell whether you are aware of the "Trivially Relocatable"=20
>> proposal. Here's a blog post on it with a draft paper:=20
>> https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-reloc=
atable/
>> =20
>>
>> It's a bit like P1029 though, but it addresses the one concern that you=
=20
>> have for P1029.
>>
>>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/4575cd99-deda-4cae-8ca0-56cb44e5622b%40isocpp.or=
g.
------=_Part_867_1791482099.1533923411384
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, August 10, 2018 at 8:19:01 PM UTC+3, fl=
oria...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr">No, I was not aware of this very proposal. (That's quite har=
d to keep track of all proposals)<br><br>However, it also shares some issue=
s with most other proposals.<br>Namely: it talks about destructive move (tw=
o different storages, moving the actual object from one to the other).<br><=
/div></blockquote><div><br></div><div>Destructive move handles self referen=
tial, this one does not (by design).</div><div><br></div><div>In that sense=
yours more like destructive then it :)</div><div><br></div><div><br></div>=
<div>Anyway, the issue I see is the fact, it is not clear how it is communi=
cated by the language when it is to be called.</div><div><span style=3D"dis=
play: inline !important; float: none; background-color: transparent; color:=
rgb(34, 34, 34); font-family: "Arial","Helvetica",sans=
-serif; font-size: 13px; font-style: normal; font-variant: normal; font-wei=
ght: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decora=
tion: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-wid=
th: 0px; white-space: normal; word-spacing: 0px;">Because "when the ad=
dress changes" is not a language category.=C2=A0 What are the rules, w=
hen should the compiler emit it.=C2=A0</span></div><div><br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Also=
, only trivial destructive moves are considered (no user defined).<br><br>B=
ut my proposal talks about in-place relocation: there is one single storage=
whose address has changed.<br>And the relocation can be user-defined (a st=
d::list could be made nothrow relocatable).<br><br>Le vendredi 10 ao=C3=BBt=
2018 19:08:06 UTC+2, Nicolas Lesser a =C3=A9crit=C2=A0:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">I can't tell whether you are aw=
are of the "Trivially Relocatable" proposal. Here's a blog po=
st on it with a draft paper:=C2=A0<a onmousedown=3D"this.href=3D'https:=
//www.google.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.io%2Fblog%2F2018=
%2F07%2F18%2Fannouncing-trivially-relocatable%2F\x26sa\x3dD\x26sntz\x3d1\x2=
6usg\x3dAFQjCNGEA9QMgWs5WBFLICjqL2WLBLKLIg';return true;" onclick=3D"th=
is.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.gi=
thub.io%2Fblog%2F2018%2F07%2F18%2Fannouncing-trivially-relocatable%2F\x26sa=
\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGEA9QMgWs5WBFLICjqL2WLBLKLIg';return=
true;" href=3D"https://quuxplusone.github.io/blog/2018/07/18/announcing-tr=
ivially-relocatable/" target=3D"_blank" rel=3D"nofollow">https://quuxpluson=
e.<wbr>github.io/blog/2018/07/18/<wbr>announcing-trivially-<wbr>relocatable=
/</a>=C2=A0<div><br></div><div>It's a bit like P1029 though, but it add=
resses the one concern that you have for P1029.</div></div><br></blockquote=
></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4575cd99-deda-4cae-8ca0-56cb44e5622b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4575cd99-deda-4cae-8ca0-56cb44e5622b=
%40isocpp.org</a>.<br />
------=_Part_867_1791482099.1533923411384--
------=_Part_866_27335325.1533923411384--
.
Author: florian.csdt@gmail.com
Date: Fri, 10 Aug 2018 11:32:20 -0700 (PDT)
Raw View
------=_Part_897_627172108.1533925940153
Content-Type: multipart/alternative;
boundary="----=_Part_898_204483121.1533925940154"
------=_Part_898_204483121.1533925940154
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 10 ao=C3=BBt 2018 19:50:11 UTC+2, mihailn...@gmail.com a =C3=A9=
crit :
>
>
>
> On Friday, August 10, 2018 at 8:19:01 PM UTC+3, floria...@gmail.com wrote=
:
>>
>> No, I was not aware of this very proposal. (That's quite hard to keep=20
>> track of all proposals)
>>
>> However, it also shares some issues with most other proposals.
>> Namely: it talks about destructive move (two different storages, moving=
=20
>> the actual object from one to the other).
>>
>
> Destructive move handles self referential, this one does not (by design).
>
Yes it does, you just have to write the operator relocate yourself (exactly=
=20
as you need to write copy/move constructor yourself to keep self reference=
=20
valid):
struct self_referential {
self_referential* p;
int i;
self_referential() : p(this), i() {}
self_referential(const self_referential& other) : p(this), i(other.i) {}
self_referential& operator=3D(const self_referential& other) {
i =3D other.i;
return *this;
}
~self_referential() {}
// operator relocate
void operator relocate(void*) {
p =3D this;
}
};
=20
>
> In that sense yours more like destructive then it :)
>
> I don't fully understand your sentence... But I'll try to answer.
There is absolutely no destruction involved here, there is one single=20
object throughout the entire process.
Though, destructive moves can be implemented with this: memcpy + relocate
=20
>
> Anyway, the issue I see is the fact, it is not clear how it is=20
> communicated by the language when it is to be called.
> Because "when the address changes" is not a language category. What are=
=20
> the rules, when should the compiler emit it.=20
>
Basically, relocation will be emitted only when explicitly called (eg: in=
=20
library code), or as an optimized equivalent to move+destroy but such an=20
optimization would not be mandatory.
That's true "when the address changes" is not a language category.
That's why I start to think that splitting the operation in 2 steps might=
=20
be better.
So let me explain those 2 steps:
struct Foo {
void operator delocate();
void operator relocate();
};
delocate would mean: the object has no more location (so cannot be=20
accessed) but its bit-pattern remains and can be moved around as much as=20
you like.
relocate would mean: the current location of the bit-pattern is the new=20
location of the object which is now accessible.
Every object access between those 2 operations is undefined behavior (but=
=20
reading/copying the bytes is fine).
Here is an example of how it could then be used:
int main() {
char* buf1 =3D malloc(sizeof(Foo));
char* buf2 =3D malloc(sizeof(Foo));
Foo* p1 =3D new(buf1) Foo; // object is located as buf1
Foo* p2 =3D reinterpret_cast<Foo*>(buf2); // fine as long as p2 is not=20
dereferenced
// object can be accessed through p1 only and *p2 is UB
p1->operator delocate(); // object has no more location: its bit pattern=
=20
can be moved around
// object cannot be accessed at all and both *p1 and *p2 are UB
std::memcpy(buf2, buf1, sizeof(Foo)); // copy the bit pattern from buf1=
=20
to buf2
// object still not accessible, *p1 and *p2 are UB
p2->operator relocate(); // object location has been set to buf2
// p1->operator relocate(); // this would be UB
// object is accessible through p2, *p1 is still UB
p2->~Foo(); // destroy the object
free(buf1);
free(buf2);
}
On this example, I made 2 buffers with an actual memcpy, but it can also be=
=20
applied to a single allocation + realloc without explicit copy.
On almost all types, I expect delocate() to be trivial (ie: noop).
On the majority of types, I expect relocate() to also be trivial (ie: noop)=
;
=20
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/1ff4c333-c48c-44f2-ac2b-e3b8212bde55%40isocpp.or=
g.
------=_Part_898_204483121.1533925940154
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le vendredi 10 ao=C3=BBt 2018 19:50:11 UTC+2, miha=
iln...@gmail.com a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><br><br>On Friday, August 10, 2018 at 8:19:01 PM UTC=
+3, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">No, I was not aware of this very proposal. (That's q=
uite hard to keep track of all proposals)<br><br>However, it also shares so=
me issues with most other proposals.<br>Namely: it talks about destructive =
move (two different storages, moving the actual object from one to the othe=
r).<br></div></blockquote><div><br></div><div>Destructive move handles self=
referential, this one does not (by design).</div></div></blockquote><div><=
br></div><div>Yes it does, you just have to write the operator relocate you=
rself (exactly as you need to write copy/move constructor yourself to keep =
self reference valid):</div><div><div style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> self_referential </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 self_referential</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> p</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=
=A0 self_referential</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">),</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">{}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 self_referential</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
self_referential</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> other</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">),</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> i</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">o=
ther</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">i</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 self_referential</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">operator</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">=3D(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> self_referential</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> other</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 i </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> other<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">i</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">~</span><span style=3D"color: #000;" class=3D"styled-by-prettify">self_r=
eferential</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><sp=
an style=3D"color: #800;" class=3D"styled-by-prettify">// operator relocate=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> relocate</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">*)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 p </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>this</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br><b=
r></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><div><br></div><div>In that sense yours more like destructive t=
hen it :)</div><div><br></div></div></blockquote><div>I don't fully und=
erstand your sentence... But I'll try to answer.<br></div><div><br></di=
v><div>There is absolutely no destruction involved here, there is one singl=
e object throughout the entire process.</div><div>Though, destructive moves=
can be implemented with this: memcpy + relocate<br></div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><d=
iv><br></div><div>Anyway, the issue I see is the fact, it is not clear how =
it is communicated by the language when it is to be called.</div><div><span=
style=3D"display:inline!important;float:none;background-color:transparent;=
color:rgb(34,34,34);font-family:"Arial","Helvetica",san=
s-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:40=
0;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px">Because "wh=
en the address changes" is not a language category.=C2=A0 What are the=
rules, when should the compiler emit it.=C2=A0</span></div></div></blockqu=
ote><div><br></div><div>Basically, relocation will be emitted only when exp=
licitly called (eg: in library code), or as an optimized equivalent to move=
+destroy but such an optimization would not be mandatory.</div><div><br></d=
iv><div>That's true "when the address changes" is not a langu=
age category.</div><div>That's why I start to think that splitting the =
operation in 2 steps might be better.</div><div><br></div><div>So let me ex=
plain those 2 steps:</div><div><div style=3D"background-color: rgb(250, 250=
, 250); border-color: rgb(187, 187, 187); border-style: solid; border-width=
: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> delocate</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">operator</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> relocate</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span></div></code></div></div><div><br></div><div>delocate would m=
ean: the object has no more location (so cannot be accessed) but its bit-pa=
ttern remains and can be moved around as much as you like.</div><div>reloca=
te would mean: the current location of the bit-pattern is the new location =
of the object which is now accessible.</div><div><br></div><div>Every objec=
t access between those 2 operations is undefined behavior (but reading/copy=
ing the bytes is fine).</div><div><br></div><div>Here is an example of how =
it could then be used:</div><div><div style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> main</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">char</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> buf1 </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> malloc</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Foo</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">));</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
har</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> buf2 </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> malloc</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styl=
ed-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
p1 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">new</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">buf1</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// object =
is located as buf1</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p2 </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">*>(</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">buf2</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">// fine as long as p2 is not dereferenced</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// object can be access=
ed through p1 only and *p2 is UB</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br>=C2=A0 p1</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">-></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">operator</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> delocate</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// object has no more location: its bit pattern can be moved around=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=
=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// =
object cannot be accessed at all and both *p1 and *p2 are UB</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 std</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">memcpy</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">buf2</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> buf1</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">));</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #800;" class=3D"styled-by-prettify">// copy the bit pattern from buf1 t=
o buf2</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
<br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>// object still not accessible, *p1 and *p2 are UB</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 p2</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">-></span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> relocate</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// object location has been set to buf2</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span>=
<span style=3D"color: #800;" class=3D"styled-by-prettify">// p1->operato=
r relocate(); // this would be UB</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #800;" =
class=3D"styled-by-prettify">// object is accessible through p2, *p1 is sti=
ll UB</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
br>=C2=A0 p2</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">->~</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Fo=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #800;" class=3D"styled-by-prettify">// destroy the object</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0=
free</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">buf1</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 free</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">buf2</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span></div></code></div></div><div>On this example, I =
made 2 buffers with an actual memcpy, but it can also be applied to a singl=
e allocation + realloc without explicit copy.<br></div><div><br>On almost a=
ll types, I expect delocate() to be trivial (ie: noop).</div><div>On the ma=
jority of types, I expect relocate() to also be trivial (ie: noop);<br></di=
v><div><br></div><div>=C2=A0</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1ff4c333-c48c-44f2-ac2b-e3b8212bde55%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1ff4c333-c48c-44f2-ac2b-e3b8212bde55=
%40isocpp.org</a>.<br />
------=_Part_898_204483121.1533925940154--
------=_Part_897_627172108.1533925940153--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 10 Aug 2018 12:51:28 -0700 (PDT)
Raw View
------=_Part_897_2133872952.1533930688700
Content-Type: multipart/alternative;
boundary="----=_Part_898_1583866132.1533930688700"
------=_Part_898_1583866132.1533930688700
Content-Type: text/plain; charset="UTF-8"
On Friday, August 10, 2018 at 12:41:31 PM UTC-4, floria...@gmail.com wrote:
>
> I was playing with memory allocations, what it is possible to do and how
> it is implemented.
> It made me think about relocations, so here is the result of my reflection.
>
>
> "Relocation" definition:
> An object is relocated when its address changes.
> This does not necessarily implies a copy of its bytes.
>
>
This is where we run into a problem. The C++ object model is predicated on
an object occupying a single region of storage throughout the period it
exists:
An object occupies a region of storage in its period of construction
> (15.7), throughout its lifetime (6.8), and in its period of destruction
> (15.7).
>
*Everything* about the C++ object model starts with this assumption:
objects live in a specific piece of storage. Change that, and you're now
rewriting the entire object model. The reason move in C++ was defined as
constructing/assigning-with-modification rather than what you're talking
about was precisely to avoid having to do this.
The kind of thing you're talking about is a tremendous undertaking. Your
post barely scratches the surface of the implications of it. If something
like that is going to happen, you need a skilled spec-doctor/lawyer to take
a look at whatever you're trying to do.
Furthermore, I find myself confused by these statements:
Relocation might be called explicitly by user code, or directly by the
> compiler as an optimization.
>
> I don't propose any situation where the language guarantees a relocation
> will happen.
>
That seems contradictory. If users can explicitly perform relocation, then
the langauge must be able to guarantee that there is some "situation"
wherein "a relocation will happen".
Another optimization that can be done with such a relocation (and is not
> possible with any current form relocation/destructive move) is to be able
> to std::realloc a buffer, and just fix the objects afterwards.
>
OK, let's examine this idea in greater detail. You want to be able to
`realloc` and perform object fixup.
So... what happens to the objects between `realloc` and object fixup? What
state are the objects in? What does the object model say about an object in
such a state? Can you access it? If so, with which operations?
Furthermore, what exactly does "fix the objects" mean? How does a type go
about doing that? What order are the subobjects in the object "fixed" in?
Who decides what this order is? Is this a user-defined process? And if "fix
the objects" involves running user-defined code, then what exactly can that
user-defined code do with the object?
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3f72760b-3c86-42bd-b24c-aca85684ba20%40isocpp.org.
------=_Part_898_1583866132.1533930688700
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, August 10, 2018 at 12:41:31 PM UTC-4, f=
loria...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr">I was playing with memory allocations, what it is possible to d=
o and how it is implemented.<br>It made me think about relocations, so here=
is the result of my reflection.<br><br><br><font size=3D"4">"Relocati=
on" definition:</font><br><div style=3D"margin-left:40px">An object is=
relocated when its address changes.<br>This does not necessarily implies a=
copy of its bytes.<br></div><br></div></blockquote><div><br></div><div>Thi=
s is where we run into a problem. The C++ object model is predicated on an =
object occupying a single region of storage throughout the period it exists=
:</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0p=
x 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1=
ex;"><div>An object occupies a region of storage in its period of construct=
ion (15.7), throughout its lifetime (6.8), and in its period of destruction=
(15.7).<br></div></blockquote><div><br></div><div><i>Everything</i> about =
the C++ object model starts with this assumption: objects live in a specifi=
c piece of storage. Change that, and you're now rewriting the entire ob=
ject model. The reason move in C++ was defined as constructing/assigning-wi=
th-modification rather than what you're talking about was precisely to =
avoid having to do this.<br></div><div><br></div><div>The kind of thing you=
're talking about is a tremendous undertaking. Your post barely scratch=
es the surface of the implications of it. If something like that is going t=
o happen, you need a skilled spec-doctor/lawyer to take a look at whatever =
you're trying to do.</div><div><br></div><div></div><div>Furthermore, I=
find myself confused by these statements:</div><div><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px =
solid rgb(204, 204, 204); padding-left: 1ex;"><div>Relocation might be call=
ed explicitly by user code, or directly by the compiler as an optimization.=
</div><div><br></div><div>I don't propose any situation where the langu=
age guarantees a relocation will happen.</div></blockquote><div><br></div><=
div>That seems contradictory. If users can explicitly perform relocation, t=
hen the langauge must be able to guarantee that there is some "situati=
on" wherein "a relocation will happen".</div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; borde=
r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>Another opti=
mization that can be done with such a relocation (and is not possible with =
any current form relocation/destructive move) is to be able to std::realloc=
a buffer, and just fix the objects afterwards.<br></div></blockquote><div>=
<br></div><div>OK, let's examine this idea in greater detail. You want =
to be able to `realloc` and perform object fixup.</div><div><br></div><div>=
So... what happens to the objects between `realloc` and object fixup? What =
state are the objects in? What does the object model say about an object in=
such a state? Can you access it? If so, with which operations?<br></div><d=
iv><br></div><div>Furthermore, what exactly does "fix the objects"=
; mean? How does a type go about doing that? What order are the subobjects =
in the object "fixed" in? Who decides what this order is? Is this=
a user-defined process? And if "fix the objects" involves runnin=
g user-defined code, then what exactly can that user-defined code do with t=
he object?</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3f72760b-3c86-42bd-b24c-aca85684ba20%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3f72760b-3c86-42bd-b24c-aca85684ba20=
%40isocpp.org</a>.<br />
------=_Part_898_1583866132.1533930688700--
------=_Part_897_2133872952.1533930688700--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 10 Aug 2018 12:58:01 -0700 (PDT)
Raw View
------=_Part_966_20247041.1533931081089
Content-Type: multipart/alternative;
boundary="----=_Part_967_1580213970.1533931081089"
------=_Part_967_1580213970.1533931081089
Content-Type: text/plain; charset="UTF-8"
Other issues:
If you have to "fix the object" after a non-copying, address changing
`realloc`, wouldn't it be faster to just do a memcpy? If every pointer
subobject may have to have some fixup work done based on where it points to
and the realloced range of memory, doesn't that mean that you're going to
touch every cache line in that range? OK sure, you don't have to allocate
new pages of memory and copy to that memory, but aren't there efficient
ways to handle that?
And either way, the operation is O(n) for any types that aren't trivially
relocatable. Since "fix the objects" has to happen for each object in the
range. So `vector<T>` would only be able to have O(1) reallocation if the
objects are trivially relocatable.
Also, I think you overestimate how broad "trivially relocatable" types
under your definition will be. Any type with a pointer as a subobject
cannot be trivially relocatable, since you may need pointer fixup when you
relocate it. `unique_ptr<T>` cannot be trivially relocatable, because you *don't
know* if it points to something that was relocated with it.
That is, "trivially relocatable" in your system is not a property of the
*type*; it is a property of the object's value and the mechanism of
relocation.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0a254171-7eed-4fde-b3f6-f99dd2dae7f4%40isocpp.org.
------=_Part_967_1580213970.1533931081089
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div></div><div>Other issues:</div><div><br></div><div>If =
you have to "fix the object" after a non-copying, address changin=
g `realloc`, wouldn't it be faster to just do a memcpy? If every pointe=
r subobject may have to have some fixup work done based on where it points =
to and the realloced range of memory, doesn't that mean that you're=
going to touch every cache line in that range? OK sure, you don't have=
to allocate new pages of memory and copy to that memory, but aren't th=
ere efficient ways to handle that?</div><div><br></div><div>And either way,=
the operation is O(n) for any types that aren't trivially relocatable.=
Since "fix the objects" has to happen for each object in the ran=
ge. So `vector<T>` would only be able to have O(1) reallocation if th=
e objects are trivially relocatable.</div><div><br></div><div>Also, I think=
you overestimate how broad "trivially relocatable" types under y=
our definition will be. Any type with a pointer as a subobject cannot be tr=
ivially relocatable, since you may need pointer fixup when you relocate it.=
`unique_ptr<T>` cannot be trivially relocatable, because you <i>don&=
#39;t know</i> if it points to something that was relocated with it.</div><=
div><br></div><div>That is, "trivially relocatable" in your syste=
m is not a property of the <i>type</i>; it is a property of the object'=
s value and the mechanism of relocation.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/0a254171-7eed-4fde-b3f6-f99dd2dae7f4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0a254171-7eed-4fde-b3f6-f99dd2dae7f4=
%40isocpp.org</a>.<br />
------=_Part_967_1580213970.1533931081089--
------=_Part_966_20247041.1533931081089--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Fri, 10 Aug 2018 16:19:23 -0400
Raw View
--00000000000052b57f05731a768f
Content-Type: text/plain; charset="UTF-8"
On Fri, Aug 10, 2018 at 3:51 PM Nicol Bolas <jmckesson@gmail.com> wrote:
> OK, let's examine this idea in greater detail. You want to be able to
> `realloc` and perform object fixup.
>
> So... what happens to the objects between `realloc` and object fixup? What
> state are the objects in? What does the object model say about an object in
> such a state? Can you access it? If so, with which operations?
>
> Furthermore, what exactly does "fix the objects" mean? How does a type go
> about doing that? What order are the subobjects in the object "fixed" in?
> Who decides what this order is? Is this a user-defined process? And if "fix
> the objects" involves running user-defined code, then what exactly can that
> user-defined code do with the object?
>
It rather sounds like we need something like Ada's Adjust procedure for
Controlled types:
<https://www2.adacore.com/gap-static/GNAT_Book/html/aarm/AA-7-6.html>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdZuL3yVDyRQucj4GtURYBoVqqhzqLKhV-jry8jmeJySdA%40mail.gmail.com.
--00000000000052b57f05731a768f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, Aug 10=
, 2018 at 3:51 PM Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com">jm=
ckesson@gmail.com</a>> wrote:</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><div>OK, let's examine this idea in great=
er detail. You want to be able to `realloc` and perform object fixup.</div>=
<div><br></div><div>So... what happens to the objects between `realloc` and=
object fixup? What state are the objects in? What does the object model sa=
y about an object in such a state? Can you access it? If so, with which ope=
rations?<br></div><div><br></div><div>Furthermore, what exactly does "=
fix the objects" mean? How does a type go about doing that? What order=
are the subobjects in the object "fixed" in? Who decides what th=
is order is? Is this a user-defined process? And if "fix the objects&q=
uot; involves running user-defined code, then what exactly can that user-de=
fined code do with the object?<br></div></div></blockquote><div><br>It rath=
er sounds like we need something like Ada's Adjust procedure for Contro=
lled types:<br><<a href=3D"https://www2.adacore.com/gap-static/GNAT_Book=
/html/aarm/AA-7-6.html">https://www2.adacore.com/gap-static/GNAT_Book/html/=
aarm/AA-7-6.html</a>></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAHSYqdZuL3yVDyRQucj4GtURYBoVqqhzqLKh=
V-jry8jmeJySdA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdZuL3yVDyRQ=
ucj4GtURYBoVqqhzqLKhV-jry8jmeJySdA%40mail.gmail.com</a>.<br />
--00000000000052b57f05731a768f--
.
Author: Henry Miller <hank@millerfarm.com>
Date: Fri, 10 Aug 2018 15:39:44 -0500
Raw View
This is a multi-part message in MIME format.
--_----------=_15339335848949440
Content-Type: text/plain; charset="UTF-8"
On Fri, Aug 10, 2018, at 11:41 AM, florian.csdt@gmail.com wrote:
> I was playing with memory allocations, what it is possible to do and
> how it is implemented.> It made me think about relocations, so here is the result of my
> reflection.>
>
> "Relocation" definition:
> An object is relocated when its address changes.
> This does not necessarily implies a copy of its bytes.
>
>
> When it can occur:
> This could happen if a call to realloc is performed.
> This could also happen as a compiler optimization
What about memory compaction? This would be the most interesting and
useful case to me. Memory fragmentation is an unfortunate reality that I
sometimes fight.
>
> How it can be integrated to the language:
> Relocation cannot be a constructor: no new object is created.
> Relocation cannot be an assignment operator: Only one object is
> involved.>
> So here is what I propose:
> Every type has a relocation operator that takes a pointer and
> returning void (let's call it operator relocate to ease the
> explanation, but I have no strong opinion on the syntax).> This operator is called just after the object address has changed (for
> whatever reason), and the pointer argument represents the old address
> of the object (which is now an invalid address).>
> This operator can be deleted or defaulted.
> The operator relocate is trivial iif:
> * it is not user-provided (that is, it is implicitly-defined or
> defaulted)
> * T has no virtual member functions
> * T has no virtual base classes
> * the operator relocate selected for every direct base of T is
> trivial
> * the operator relocate selected for every non-static class type (or
> array of class type) member of T is trivial> A trivial operator relocate is basically a noop.
>
> No syntax is proposed to call relocation (apart from object.operator
> relocate(p)).>
> An operator relocate shall not change the state of the object if the
> new address is the same as the old address, even if the operator is
> not trivial.> It also cannot be virtual (you shall relocate only object through
> their true type).>
> I propose that throwing relocation is allowed, but discouraged (but if
> this is problematic, I see no strong reason to keep throwing
> relocation).>
> Small example:
>
>
> struct Bar; struct Foo { Bar* bar; };
>
> struct Bar { Foo* foo; // foo.bar is always equals to this
>
> Bar() : foo(new Foo{this}) {} ~Bar() { delete foo; }
>
> // copy is deleted Bar(const Bar&) = delete; Bar& operator=(const
> Bar&) = delete;
>
> // move needs to set the foo.bar to this object Bar(Bar&& other) :
> foo(other.foo) { other.foo = nullptr; foo.bar = this; } Bar&
> operator=(Bar&& other) { swap(foo, other.foo); foo.bar = this;
> other.foo.bar = &other; return *this; }
>
> // If address has changed, reset the foo.bar to point to the new
> location of the object void operator relocate(void*) { foo.bar =
> this; } };>
>
Your example code is undefined behavior. If some other thread access
bar::foo after the reallocation and before bar::relocate gets to the fix
up line your program goes boom.
That is the easiest way to show that this can't work. There are a large
number of cases where you want to relocate an object that some other
thread is accessing. The reality is that in modern CPUs threads are
often the only way to get acceptable performance. This is why C++11
finally put threads into the object model. If you want to fall back to
undefined behavior, then you need to document exactly when things are
undefined, show that there are significant uses where you can use this
without getting undefined behavior, and make sure that "average person"
has a reasonable chance of using it correctly.
I think that the only way this can work is if the object model has
specific support for changing all pointers in an atomic way (this
implies stop all threads before doing the reallocation, doing the fix
up, then restarting threads). There are large performance considerations
here, so it better be something that you don't pay for if you don't use.
Don't get me wrong, there are real problems that relocation support in
the object model solves, but the problem is not easy.
>
> Is relocation the same as move?
> No: move is creating a new object from an expiring object.
> The expiring object might be used afterwards (eg: std::swap).
>
> With relocation, there is a single object whose address changes.
>
> Is relocation the same as destructive move?
> No: destructive move means there is a storage for both old and new
> objects at the same time, and the object is copied from the old
> storage to the new storage with the assumption that the old storage
> does not contain any living object after the move and the new storage
> does not contain any living object before the move. (destructive move
> is not part of the language yet)>
> Relocation involves a single storage, whose address has changed.
> This can happen without any byte being copied (eg: mremap).
>
> Though, a destructive move can be implemented as memcpy + relocate for
> any relocatable object (not only trivial ones).>
> When is relocation called?
> Relocation might be called explicitly by user code, or directly by the
> compiler as an optimization.>
> I don't propose any situation where the language guarantees a
> relocation will happen.> I propose to allow the compiler to do (memcpy +) relocation instead of
> move + destruct without giving any guarantee.> The STL containers would need to be modified to take advantage of
> relocation.>
> What are the advantages of relocation?
> Most advantages are better optimizations.
>
> An obvious optimization that most people try to achieve with
> destructive moves is to be able to memcpy a buffer of objects into a
> larger buffer (for instance in std::vector<std::unique_ptr<T>>).> Regular moves cannot do that.
>
> Another one is the possibility to have "moveable" objects without the
> need to have an empty state.>
> Relocation would also enable some types to be relocated without
> throwing while their move constructor can throw.>
> Another optimization that can be done with such a relocation (and is
> not possible with any current form relocation/destructive move) is to
> be able to std::realloc a buffer, and just fix the objects afterwards.> Most realloc implementations will not perform any copy if the buffer
> is large enough (only page remapping).> This is why relocation needs to work on a single storage whose address
> has changed.>
> This last point means that growing a vector can be made O(1) for any
> trivially relocatable types (using std::realloc which is O(1) on most
> implementations).> (this was the starting point of my thinking)
>
>
> What types would be trivially relocatable without being neither
> trivially copyable nor trivially movable:> Actually, many types would be trivially relocatable:
> * std::unique_ptr
> * std::shared_ptr
> * std::string
> * std::vector
> * std::map (?)
> * std::unordered_map (?)
> * std::deque (?)
> * ...>
> Considering current implementations, std::list will most likely not be
> trivially relocatable but surely can be nothrow relocatable.>
> How does it relate to other proposals?
>
> Destructive Move (N4034[1]):
> N4034 is a form of destructive move, so cannot handle std::realloc.> Every feature of N4034 is covered by relocation.
>
> Relocator: Efficiently moving objects (P0023r0)[2]:
> P0023r0 is a form of destructive move, so cannot handle std::realloc.> Every feature of P0023r0 is covered by my proposed relocation.
>
> Compared to N4034, P0023r0 mentions "in-place relocation" which would
> be feature equivalent to my proposed relocation.> P0023r0 also proposes a usable syntax to define relocators that can
> call subobjects relocators which is similar to a constructor (yet is
> different).>
> [[move_relocates]] (P1029r0):[3]
> P1029r0 is not about the general concept of relocation, but only about
> trivial relocation.> P1029r0 proposes an attribute to decorate a move constructor to let
> the compiler know a type is trivially relocatable.>
> [[move_relocates]] would be equivalent to trivially relocatable types.> The rules for implicit operator relocate would lead to most types
> being automatically trivially relocatable without any code change.>
> Zero-overhead deterministic exceptions: Throwing values (P0709r1[4]):> That proposal is not about relocation nor destructive move whatsoever.> P0709r1 explicitly mandates that std::error must be trivially
> destructive movable (which is designated by the term "trivially
> relocatable").> That proposal could then take advantage of the relocation I propose.>
>
> Low level le i/o library (P1031R1[5]):
> That proposal is not about relocation nor destructive move whatsoever.> "persistify + unpersistify" an object in a mapped memory region can be
> seen as a relocation.>
> That proposal could benefit from my relocation proposal, especially
> trivially relocatable types.> However, operator relocate takes the old address as argument. This
> address would not be accessible when blessing the new object from the
> storage.> This could be solved by allowing the operator relocate to not take any
> address.>
> Or we could introduce a pair of methods taking no argument:
> delocate()/relocate().> The meaning would be: delocate() + address change + relocate() would
> be equivalent to address change + relocate(void*)> We can discuss those possibilities directly on the thread of that
> proposal[6]>
> Open questions
> * What should be the syntax to define/call relocation?
> * Is taking the old address as argument really needed?
> * Would a 2 step relocation make more sense?
> * Could relocation throw?
> * Should a non-copyable, non movavble type be implicitly relocatable?>
>
>
> I hope you will find this proposal interesting, and I would be pleased
> to answer any question about it.>
> Florian
>
> --
> You received this message because you are subscribed to the Google
> Groups "ISO C++ Standard - Future Proposals" group.> To unsubscribe from this group and stop receiving emails from it,
> send an email to std-proposals+unsubscribe@isocpp.org.> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org[7].
Links:
1. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4034.pdf
2. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0023r0.pdf
3. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1029r0.pdf
4. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r1.pdf
5. https://docs.google.com/viewer?a=v&pid=forums&srcid=MTEwODAzNzI2MjM1OTc0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQUFKATAuMQFpc29jcHAub3JnAXYy&authuser=0
6. https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/bk8esqk-Qoo
7. https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org?utm_medium=email&utm_source=footer
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1533933584.894944.1470306312.0E21362C%40webmail.messagingengine.com.
--_----------=_15339335848949440
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="UTF-8"
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type=3D"text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style>
</head>
<body><div style=3D"font-family:Arial;"><br></div>
<div><br></div>
<div><br></div>
<div>On Fri, Aug 10, 2018, at 11:41 AM, <a href=3D"mailto:florian.csdt@gmai=
l.com">florian.csdt@gmail.com</a> wrote:<br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial;=
">I was playing with memory allocations, what it is possible to do and how =
it is implemented.<br></div>
<div style=3D"font-family:Arial;">It made me think about relocations, so he=
re is the result of my reflection.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">"Relocation" definition:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">An objec=
t is relocated when its address changes.<br></div>
<div style=3D"font-family:Arial;">This does not necessarily implies a copy =
of its bytes.<br></div>
</div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">When it can occur:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">This cou=
ld happen if a call to realloc is performed.<br></div>
<div style=3D"font-family:Arial;">This could also happen as a compiler opti=
mization<br></div>
</div>
</div>
</blockquote><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">What about memory compaction? This would =
be the most interesting and useful case to me. Memory fragmentation is an u=
nfortunate reality that I sometimes fight. </div>
<div style=3D"font-family:Arial;"><br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial;=
"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">How it can be integrated to the language:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">Relocati=
on cannot be a constructor: no new object is created.<br></div>
<div style=3D"font-family:Arial;">Relocation cannot be an assignment operat=
or: Only one object is involved.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">So here is what I propose:<br></div>
<div style=3D"font-family:Arial;">Every type has a relocation operator that=
takes a pointer and returning <span class=3D"font" style=3D"font-family:&q=
uot;courier new", monospace">void</span> (let's call it <span class=3D=
"font" style=3D"font-family:"courier new", monospace">operator re=
locate</span> to ease the explanation, but I have no strong opinion on the =
syntax).<br></div>
<div style=3D"font-family:Arial;">This operator is called just after the ob=
ject address has changed (for whatever reason), and the pointer argument re=
presents the old address of the object (which is now an invalid address).<b=
r></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">This operator can be deleted or defaulted=
..<br></div>
<div style=3D"font-family:Arial;">The <span class=3D"font" style=3D"font-fa=
mily:"courier new", monospace">operator relocate</span> is trivia=
l iif:<br></div>
</div>
<ul style=3D"margin-left:40px;"><li>it is not user-provided (that is, it is=
implicitly-defined or defaulted)<span><span></span></span><br></li><li><co=
de>T</code> has no virtual member functions<br></li><li><code>T</code> has =
no virtual base classes<br></li><li>the <span class=3D"font" style=3D"font-=
family:"courier new", monospace">operator relocate</span> selecte=
d for every direct base of <code>T</code> is trivial<br></li><li>the <span =
class=3D"font" style=3D"font-family:"courier new", monospace">ope=
rator relocate</span> selected for every non-static class type (or array of=
class type) member of <code>T</code> is trivial<br></li></ul><p style=3D"m=
argin-left:40px;">A trivial <span class=3D"font" style=3D"font-family:"=
;courier new", monospace">operator relocate</span> is basically a noop=
..<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40p=
x;">No syntax is proposed to call relocation (apart from <span class=3D"fon=
t" style=3D"font-family:"courier new", monospace">object.operator=
relocate(p)</span>).<br></p><p style=3D"margin-left:40px;"><br></p><p styl=
e=3D"margin-left:40px;">An <span class=3D"font" style=3D"font-family:"=
courier new", monospace">operator relocate</span> shall not change the=
state of the object if the new address is the same as the old address, eve=
n if the operator is not trivial.<br></p><p style=3D"margin-left:40px;">It =
also cannot be virtual (you shall relocate only object through their true t=
ype).<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left=
:40px;">I propose that throwing relocation is allowed, but discouraged (but=
if this is problematic, I see no strong reason to keep throwing relocation=
).<br></p><p><br></p><p><span class=3D"size" style=3D"font-size:large">Smal=
l example:</span><br></p><p style=3D"margin-left:40px;"><br></p><div style=
=3D"background-color:rgb(250, 250, 250);border-top-color:rgb(187, 187, 187)=
;border-right-color:rgb(187, 187, 187);border-bottom-color:rgb(187, 187, 18=
7);border-left-color:rgb(187, 187, 187);border-top-style:solid;border-right=
-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-w=
idth:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1=
px;overflow-wrap:break-word;"><div style=3D"font-family:Arial;"><code></cod=
e><br></div>
<div><code><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">struct</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colou=
r" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D=
"color:rgb(0, 0, 0)"><br></span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 136)">struct</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
> </span><span class=3D"colour" style=3D"color:rgb(102, 0, 102)">Foo</span>=
<span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"=
colour" style=3D"color:rgb(102, 102, 0)">{</span><span class=3D"colour" sty=
le=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D=
"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rg=
b(102, 102, 0)">*</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
> bar</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span=
><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></span><span class=
=3D"colour" style=3D"color:rgb(102, 102, 0)">};</span><span class=3D"colour=
" style=3D"color:rgb(0, 0, 0)"><br><br></span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 136)">struct</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 0, 1=
02)">Bar</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">{</span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"c=
olour" style=3D"color:rgb(102, 0, 102)">Foo</span><span class=3D"colour" st=
yle=3D"color:rgb(102, 102, 0)">*</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> // foo=
..bar is always equals to this<br><br> </span><span class=3D"colour" s=
tyle=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"c=
olor:rgb(102, 102, 0)">()</span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">:<=
/span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> foo</span><span =
class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</span><span class=3D"co=
lour" style=3D"color:rgb(0, 0, 136)">new</span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(1=
02, 0, 102)">Foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">this</spa=
n><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">})</span><span cl=
ass=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" =
style=3D"color:rgb(102, 102, 0)">{}</span><span class=3D"colour" style=3D"c=
olor:rgb(0, 0, 0)"><code><span class=3D"colour" style=3D"color:rgb(0, 0, 0)=
"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)"=
>~</span><span class=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">()</span><span clas=
s=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" st=
yle=3D"color:rgb(102, 102, 0)">{</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D"co=
lor:rgb(0, 0, 136)">delete</span><span class=3D"colour" style=3D"color:rgb(=
0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)=
">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> </=
span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">}</span><span =
class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></span></code><br> =
// copy is deleted<br> </span><span class=3D"colour" style=3D"color:r=
gb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">(</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">const=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span cl=
ass=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"co=
lour" style=3D"color:rgb(102, 102, 0)">&)</span><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">delete</=
span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span =
class=3D"colour" style=3D"color:rgb(0, 0, 0)"><code><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=
=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color=
:rgb(102, 102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0,=
0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">opera=
tor</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D(</spa=
n><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">const</span><span c=
lass=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour"=
style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D=
"color:rgb(102, 102, 0)">&)</span><span class=3D"colour" style=3D"color=
:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><=
span class=3D"colour" style=3D"color:rgb(0, 0, 136)">delete</span><span cla=
ss=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colou=
r" style=3D"color:rgb(0, 0, 0)"><br><br> // move needs to set the foo=
..bar to this object<br></span></code> </span><span class=3D"colour" s=
tyle=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"c=
olor:rgb(102, 102, 0)">(</span><span class=3D"colour" style=3D"color:rgb(10=
2, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0=
)">&&</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> ot=
her</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">)</span><=
span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"c=
olour" style=3D"color:rgb(102, 102, 0)">:</span><span class=3D"colour" styl=
e=3D"color:rgb(0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:r=
gb(102, 102, 0)">(</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)=
">other</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">foo</span><span clas=
s=3D"colour" style=3D"color:rgb(102, 102, 0)">)</span><span class=3D"colour=
" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"colo=
r:rgb(102, 102, 0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"><br> other</span><span class=3D"colour" style=3D"color:rg=
b(102, 102, 0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
>foo </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 136)">nullptr</span><span class=3D"col=
our" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 0)"><br> foo</span><span class=3D"colour" =
style=3D"color:rgb(102, 102, 0)">.</span><span class=3D"colour" style=3D"co=
lor:rgb(0, 0, 0)">bar </span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </=
span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">this</span><span=
class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"c=
olour" style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour=
" style=3D"color:rgb(102, 102, 0)">}</span><span class=3D"colour" style=3D"=
color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D"color=
:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> =
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">operator</span=
><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D(</span><span c=
lass=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"c=
olour" style=3D"color:rgb(102, 102, 0)">&&</span><span class=3D"col=
our" style=3D"color:rgb(0, 0, 0)"> other</span><span class=3D"colour" style=
=3D"color:rgb(102, 102, 0)">)</span><span class=3D"colour" style=3D"color:r=
gb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)=
">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> &n=
bsp; swap</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</=
span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">foo</span><span cl=
ass=3D"colour" style=3D"color:rgb(102, 102, 0)">,</span><span class=3D"colo=
ur" style=3D"color:rgb(0, 0, 0)"> other</span><span class=3D"colour" style=
=3D"color:rgb(102, 102, 0)">.</span><span class=3D"colour" style=3D"color:r=
gb(0, 0, 0)">foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">);</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> =
foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span><span=
class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span class=3D=
"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0=
)"><br> other</span><span class=3D"colour" style=3D"color:rgb(=
102, 102, 0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">f=
oo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.</span><s=
pan class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span><span class=3D=
"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0, =
0, 0)">other</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=
;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> &nbs=
p; </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">return</spa=
n><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(102, 102, 0)">*</span><span class=3D"colour"=
style=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"=
color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 0)"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">}</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br><br=
> // If address has changed, reset the foo.bar to point to the new lo=
cation of the object<br> </span><span class=3D"colour" style=3D"color=
:rgb(0, 0, 136)">void</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">operator=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> relocate</span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 136)">void</span><span class=3D"colour=
" style=3D"color:rgb(102, 102, 0)">*)</span><span class=3D"colour" style=3D=
"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br>&=
nbsp; foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span cla=
ss=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" s=
tyle=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"co=
lor:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, =
0, 0)"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 102=
, 0)">}</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></spa=
n><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">};</span><span cl=
ass=3D"colour" style=3D"color:rgb(0, 0, 0)"></span></code></div>
<div style=3D"font-family:Arial;"><code></code><br></div>
</div>
<p><br></p></div>
</blockquote><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">Your example code is undefined behavior. =
If some other thread access bar::foo after the reallocation and before bar:=
:relocate gets to the fix up line your program goes boom. <br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">That is the easiest way to show that this=
can't work. There are a large number of cases where you want to relocate a=
n object that some other thread is accessing. The reality is that in modern=
CPUs threads are often the only way to get acceptable performance. This is=
why C++11 finally put threads into the object model. If you want to fall b=
ack to undefined behavior, then you need to document exactly when things ar=
e undefined, show that there are significant uses where you can use this wi=
thout getting undefined behavior, and make sure that "average person" has a=
reasonable chance of using it correctly.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">I think that the only way this can work i=
s if the object model has specific support for changing all pointers in an =
atomic way (this implies stop all threads before doing the reallocation, do=
ing the fix up, then restarting threads). There are large performance consi=
derations here, so it better be something that you don't pay for if you don=
't use. <br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">Don't get me wrong, there are real proble=
ms that relocation support in the object model solves, but the problem is n=
ot easy. </div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><p><br></p><p><span class=3D"siz=
e" style=3D"font-size:large">Is relocation the same as move?</span><br></p>=
<p style=3D"margin-left:40px;">No: move is creating a new object from an ex=
piring object.<br></p><p style=3D"margin-left:40px;">The expiring object mi=
ght be used afterwards (eg: std::swap).<br></p><p style=3D"margin-left:40px=
;"><br></p><p style=3D"margin-left:40px;">With relocation, there is a singl=
e object whose address changes.<br></p><p><br></p><p><span class=3D"size" s=
tyle=3D"font-size:large">Is relocation the same as destructive move?</span>=
<br></p><p style=3D"margin-left:40px;">No: destructive move means there is =
a storage for both old and new objects at the same time, and the object is =
copied from the old storage to the new storage with the assumption that the=
old storage does not contain any living object after the move and the new =
storage does not contain any living object before the move. (destructive mo=
ve is not part of the language yet)<br></p><p style=3D"margin-left:40px;"><=
br></p><p style=3D"margin-left:40px;">Relocation involves a single storage,=
whose address has changed.<br></p><p style=3D"margin-left:40px;">This can =
happen without any byte being copied (eg: mremap).<br></p><p style=3D"margi=
n-left:40px;"><br></p><p style=3D"margin-left:40px;">Though, a destructive =
move can be implemented as memcpy + relocate for any relocatable object (no=
t only trivial ones).<br></p><p><br></p><p><span class=3D"size" style=3D"fo=
nt-size:large">When is relocation called?</span><br></p><p style=3D"margin-=
left:40px;">Relocation might be called explicitly by user code, or directly=
by the compiler as an optimization.<br></p><p style=3D"margin-left:40px;">=
<br></p><p style=3D"margin-left:40px;">I don't propose any situation where =
the language guarantees a relocation will happen.<br></p><p style=3D"margin=
-left:40px;">I propose to allow the compiler to do (memcpy +) relocation in=
stead of move + destruct without giving any guarantee.<br></p><p style=3D"m=
argin-left:40px;">The STL containers would need to be modified to take adva=
ntage of relocation.<br></p><p><br></p><p><span class=3D"size" style=3D"fon=
t-size:large">What are the advantages of relocation?</span><br></p><p style=
=3D"margin-left:40px;">Most advantages are better optimizations.<br></p><p =
style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40px;">An obvio=
us optimization that most people try to achieve with destructive moves is t=
o be able to memcpy a buffer of objects into a larger buffer (for instance =
in std::vector<std::unique_ptr<T>>).<br></p><p style=3D"margin-=
left:40px;">Regular moves cannot do that.<br></p><p style=3D"margin-left:40=
px;"><br></p><p style=3D"margin-left:40px;">Another one is the possibility =
to have "moveable" objects without the need to have an empty state.<br></p>=
<p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40px;">Reloc=
ation would also enable some types to be relocated without throwing while t=
heir move constructor can throw.<br></p><p style=3D"margin-left:40px;"><br>=
</p><p style=3D"margin-left:40px;">Another optimization that can be done wi=
th such a relocation (and is not possible with any current form relocation/=
destructive move) is to be able to <span class=3D"font" style=3D"font-famil=
y:"courier new", monospace">std::realloc</span> a buffer, and jus=
t fix the objects afterwards.<br></p><p style=3D"margin-left:40px;">Most re=
alloc implementations will not perform any copy if the buffer is large enou=
gh (only page remapping).<br></p><p style=3D"margin-left:40px;">This is why=
relocation needs to work on a single storage whose address has changed.<br=
></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40px;">=
This last point means that growing a vector can be made O(1) for any trivia=
lly relocatable types (using <span class=3D"font" style=3D"font-family:&quo=
t;courier new", monospace">std::realloc</span> which is O(1) on most i=
mplementations).<br></p><p style=3D"margin-left:40px;">(this was the starti=
ng point of my thinking)<br></p><p><br></p><p><br></p><p><span class=3D"siz=
e" style=3D"font-size:large">What types would be trivially relocatable with=
out being neither trivially copyable nor trivially movable:</span><br></p><=
p style=3D"margin-left:40px;">Actually, many types would be trivially reloc=
atable:<br></p><ul style=3D"margin-left:40px;"><li>std::unique_ptr<br></li>=
<li>std::shared_ptr<br></li><li>std::string<br></li><li>std::vector<br></li=
><li>std::map (?)<br></li><li>std::unordered_map (?)<br></li><li>std::deque=
(?)<br></li><li>...<br></li></ul><p style=3D"margin-left:40px;"><br></p><p=
style=3D"margin-left:40px;">Considering current implementations, std::list=
will most likely not be trivially relocatable but surely can be nothrow re=
locatable.<br></p><p><br></p><p><span class=3D"size" style=3D"font-size:lar=
ge">How does it relate to other proposals?</span><br></p><p><br></p><p>Dest=
ructive Move <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/=
2014/n4034.pdf">(N4034</a>):<br></p><p style=3D"margin-left:40px;">N4034 is=
a form of destructive move, so cannot handle <span class=3D"font" style=3D=
"font-family:"courier new", monospace">std::realloc</span>.<br></=
p><p style=3D"margin-left:40px;">Every feature of N4034 is covered by reloc=
ation.<br></p><p><br></p><p>Relocator: Efficiently moving objects (<a href=
=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0023r0.pdf">P0=
023r0)</a>:<br></p><p style=3D"margin-left:40px;">P0023r0 is a form of dest=
ructive move, so cannot handle <span class=3D"font" style=3D"font-family:&q=
uot;courier new", monospace">std::realloc</span>.<br></p><p style=3D"m=
argin-left:40px;">Every feature of P0023r0 is covered by my proposed reloca=
tion.<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left=
:40px;">Compared to N4034, P0023r0 mentions "in-place relocation" which wou=
ld be feature equivalent to my proposed relocation.<br></p><p style=3D"marg=
in-left:40px;">P0023r0 also proposes a usable syntax to define relocators t=
hat can call subobjects relocators which is similar to a constructor (yet i=
s different).<br></p><p><br></p><p>[[move_relocates]] (<a href=3D"http://ww=
w.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1029r0.pdf">P1029r0):</a><b=
r></p><p style=3D"margin-left:40px;">P1029r0 is not about the general conce=
pt of relocation, but only about trivial relocation.<br></p><p style=3D"mar=
gin-left:40px;">P1029r0 proposes an attribute to decorate a move constructo=
r to let the compiler know a type is trivially relocatable.<br></p><p style=
=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40px;">[[move_reloca=
tes]] would be equivalent to trivially relocatable types.<br></p><p style=
=3D"margin-left:40px;">The rules for implicit <span class=3D"font" style=3D=
"font-family:"courier new", monospace">operator relocate</span> w=
ould lead to most types being automatically trivially relocatable without a=
ny code change.<br></p><p style=3D"margin-left:40px;"><br></p><p>Zero-overh=
ead deterministic exceptions: Throwing values (<a href=3D"http://www.open-s=
td.org/jtc1/sc22/wg21/docs/papers/2018/p0709r1.pdf">P0709r1</a>):<br></p><p=
style=3D"margin-left:40px;">That proposal is not about relocation nor dest=
ructive move whatsoever.<br></p><p style=3D"margin-left:40px;">P0709r1 expl=
icitly mandates that std::error must be trivially destructive movable (whic=
h is designated by the term "trivially relocatable").<br></p><p style=3D"ma=
rgin-left:40px;">That proposal could then take advantage of the relocation =
I propose.<br></p><p><br></p><p><br></p><p>Low level le i/o library (<a hre=
f=3D"https://docs.google.com/viewer?a=3Dv&pid=3Dforums&srcid=3DMTEw=
ODAzNzI2MjM1OTc0MjE3MjkBMTYxMjc1MjI5NzM5MzM3Nzk5NTYBT0RwWFc3dXFDQUFKATAuMQF=
pc29jcHAub3JnAXYy&authuser=3D0">P1031R1</a>):<br></p><p style=3D"margin=
-left:40px;">That proposal is not about relocation nor destructive move wha=
tsoever.<br></p><p style=3D"margin-left:40px;">"persistify + unpersistify" =
an object in a mapped memory region can be seen as a relocation.<br></p><p =
style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40px;">That pro=
posal could benefit from my relocation proposal, especially trivially reloc=
atable types.<br></p><p style=3D"margin-left:40px;">However, operator reloc=
ate takes the old address as argument. This address would not be accessible=
when blessing the new object from the storage.<br></p><p style=3D"margin-l=
eft:40px;">This could be solved by allowing the operator relocate to not ta=
ke any address.<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"m=
argin-left:40px;">Or we could introduce a pair of methods taking no argumen=
t: <span class=3D"font" style=3D"font-family:"courier new", monos=
pace">delocate()/relocate()</span>.<br></p><p style=3D"margin-left:40px;">T=
he meaning would be: <span class=3D"font" style=3D"font-family:"courie=
r new", monospace">delocate() + address change + relocate()</span> wou=
ld be equivalent to <span class=3D"font" style=3D"font-family:"courier=
new", monospace">address change + relocate(void*)</span><br></p><p st=
yle=3D"margin-left:40px;">We can discuss those possibilities directly on th=
e <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-propo=
sals/bk8esqk-Qoo">thread of that proposal</a><br></p><p><br></p><p><span cl=
ass=3D"size" style=3D"font-size:large">Open questions</span><br></p><ul><li=
>What should be the syntax to define/call relocation?<br></li><li>Is taking=
the old address as argument really needed?<br></li><li>Would a 2 step relo=
cation make more sense?<br></li><li>Could relocation throw?<br></li><li>Sho=
uld a non-copyable, non movavble type be implicitly relocatable?<br></li></=
ul><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">I hope you will find this proposal intere=
sting, and I would be pleased to answer any question about it.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">Florian<br></div>
</div>
<p><br></p><div style=3D"font-family:Arial;">--<br></div>
<div style=3D"font-family:Arial;"> You received this message because you ar=
e subscribed to the Google Groups "ISO C++ Standard - Future Proposals" gro=
up.<br></div>
<div style=3D"font-family:Arial;"> To unsubscribe from this group and stop =
receiving emails from it, send an email to <a href=3D"mailto:std-proposals+=
unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br></div>
<div style=3D"font-family:Arial;"> To post to this group, send email to <a =
href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br><=
/div>
<div style=3D"font-family:Arial;"> To view this discussion on the web visit=
<a href=3D"https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19=
d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org?utm_medium=3Demail&utm_=
source=3Dfooter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposa=
ls/19d8d86c-f4cf-47a9-bb42-9e2ba06dccab%40isocpp.org</a>.<br></div>
</blockquote></body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1533933584.894944.1470306312.0E21362C=
%40webmail.messagingengine.com?utm_medium=3Demail&utm_source=3Dfooter">http=
s://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1533933584.894944.=
1470306312.0E21362C%40webmail.messagingengine.com</a>.<br />
--_----------=_15339335848949440--
.
Author: florian.csdt@gmail.com
Date: Fri, 10 Aug 2018 14:22:53 -0700 (PDT)
Raw View
------=_Part_909_591342614.1533936173191
Content-Type: multipart/alternative;
boundary="----=_Part_910_54720068.1533936173193"
------=_Part_910_54720068.1533936173193
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
@Nicol
Le vendredi 10 ao=C3=BBt 2018 21:51:28 UTC+2, Nicol Bolas a =C3=A9crit :
>
>
>
> On Friday, August 10, 2018 at 12:41:31 PM UTC-4, floria...@gmail.com=20
> wrote:
>>
>> I was playing with memory allocations, what it is possible to do and how=
=20
>> it is implemented.
>> It made me think about relocations, so here is the result of my=20
>> reflection.
>>
>>
>> "Relocation" definition:
>> An object is relocated when its address changes.
>> This does not necessarily implies a copy of its bytes.
>>
>>
> This is where we run into a problem. The C++ object model is predicated o=
n=20
> an object occupying a single region of storage throughout the period it=
=20
> exists:
>
This doesn't change this view: an object cannot occupy more than one=20
region. However, the region can be moved by some user code.
=20
>
> An object occupies a region of storage in its period of construction=20
>> (15.7), throughout its lifetime (6.8), and in its period of destruction=
=20
>> (15.7).
>>
>
> *Everything* about the C++ object model starts with this assumption:=20
> objects live in a specific piece of storage. Change that, and you're now=
=20
> rewriting the entire object model. The reason move in C++ was defined as=
=20
> constructing/assigning-with-modification rather than what you're talking=
=20
> about was precisely to avoid having to do this.
>
> The kind of thing you're talking about is a tremendous undertaking. Your=
=20
> post barely scratches the surface of the implications of it. If something=
=20
> like that is going to happen, you need a skilled spec-doctor/lawyer to ta=
ke=20
> a look at whatever you're trying to do.
>
>
First, modifying the object model is fine, a big task, but fine if done=20
right.
I will need help for sure, but I'm pretty sure it's worth a try.
And that's exactly why I posted this here. And your help is already=20
welcomed ;)
=20
> Furthermore, I find myself confused by these statements:
>
> Relocation might be called explicitly by user code, or directly by the=20
>> compiler as an optimization.
>>
>> I don't propose any situation where the language guarantees a relocation=
=20
>> will happen.
>>
>
> That seems contradictory. If users can explicitly perform relocation, the=
n=20
> the langauge must be able to guarantee that there is some "situation"=20
> wherein "a relocation will happen".
>
>
That's why I now think to have 2 operators: one to say the object is not=20
accessible but its bytes still are and can be copied/moved around.
And the other to rematerialize the object from the bytes, even if the bytes=
=20
have been moved.
So the situation where a relocation will happen is bounded by these 2=20
operations. Every access to the object between these is UB, But accesses to=
=20
the underlying bytes are fine.
=20
> Another optimization that can be done with such a relocation (and is not=
=20
>> possible with any current form relocation/destructive move) is to be abl=
e=20
>> to std::realloc a buffer, and just fix the objects afterwards.
>>
>
> OK, let's examine this idea in greater detail. You want to be able to=20
> `realloc` and perform object fixup.
>
> So... what happens to the objects between `realloc` and object fixup? Wha=
t=20
> state are the objects in? What does the object model say about an object =
in=20
> such a state? Can you access it? If so, with which operations?
>
First, let's replace realloc by delocate as I think it's much simpler to=20
reason about (a realloc could happen after delocate if you want).
So after a delocate, the object has no localisation: it is unreachable. The=
=20
only way to make reachable (possibly at another address) it to relocate the=
=20
same byte-sequence. Every accesses to the bytes directly are fine. (so=20
reading might give some unspecified result?)
=20
>
> Furthermore, what exactly does "fix the objects" mean? How does a type go=
=20
> about doing that? What order are the subobjects in the object "fixed" in?=
=20
> Who decides what this order is? Is this a user-defined process? And if "f=
ix=20
> the objects" involves running user-defined code, then what exactly can th=
at=20
> user-defined code do with the object?
>
Fix the object means: the state before delocate and after relocate is the=
=20
same. If you cannot guarantee that for your type, you should delete=20
relocation.
I think the order should not matter that much.
So I propose, for a compiler generated delocate, the same order as the=20
destructor, and for relocate, the same order as constructor.
For a user-defined relocation, it's up to the user.
For a user defined relocation, I propose that all members are still=20
accessible until the end of the delocate operator (allows to skip some=20
delocation code of some members if you know it's fine).
And for relocation, all objects are accessible from the start of the=20
relocate operator (identically, you could skip relocation of some members).
As all fundamental types are trivially relocatable, that's fine.
Within those two operators, rules are the same as elsewhere. You would just=
=20
need to be careful as some pointers might point to the old storage, so=20
shouldn't be dereferenced, but this is not a special rule.
That makes me think that a struct with references should not be relocatable=
=20
as you cannot rebind a reference.
Other issues:
>
> If you have to "fix the object" after a non-copying, address changing=20
> `realloc`, wouldn't it be faster to just do a memcpy? If every pointer=20
> subobject may have to have some fixup work done based on where it points =
to=20
> and the realloced range of memory, doesn't that mean that you're going to=
=20
> touch every cache line in that range? OK sure, you don't have to allocate=
=20
> new pages of memory and copy to that memory, but aren't there efficient=
=20
> ways to handle that?
>
If you do a memcpy, you still need the fixup step.
How can newpages+memcpy+fixup being faster than fixup only?
Also, pointers are trivially relocatable: if you have a pointer relocate=20
it, the value of the pointer will not change. If the pointer points within=
=20
the realloc'ed region, then your relocate operators are probably wrong.
The fastest way to allocate new pages and copy the content from the=20
previous pages is to create a copy-on-write shared pages. I'm not sure how=
=20
easy it is do that after you have allocated the pages the first time.
But that doesn't really change the issue, does it?
=20
>
> And either way, the operation is O(n) for any types that aren't trivially=
=20
> relocatable. Since "fix the objects" has to happen for each object in the=
=20
> range. So `vector<T>` would only be able to have O(1) reallocation if the=
=20
> objects are trivially relocatable.
>
First, growing a vector for non trivially relocatable types will remain=20
amortized O(1). But even then, I think it can still benefit from relocation=
=20
as you will need to modify only a few part of your objects.
=20
>
> Also, I think you overestimate how broad "trivially relocatable" types=20
> under your definition will be. Any type with a pointer as a subobject=20
> cannot be trivially relocatable, since you may need pointer fixup when yo=
u=20
> relocate it. `unique_ptr<T>` cannot be trivially relocatable, because you=
=20
> don't know if it points to something that was relocated with it.
>
You underestimate what trivially relocatable is: a pointer is trivially=20
relocatable.
After a call to delocate, every pointers to the object are invalidated and=
=20
should not be accessed as objects, can only be accessed as bytes.
Like that, if you try to relocate the content of the unique_ptr, the=20
pointer within unique_ptr will be invalidated, thus will be undefined=20
behavior.
In short, you cannot relocate the objects of a unique_ptr at the same time=
=20
as the unique_ptr itself.
If you want to do that (because you have a total control on how the=20
unique_ptr does its allocations), you would need to wrap the unique_ptr=20
into another object, and write this other object relocation in the way you=
=20
want.
=20
>
> That is, "trivially relocatable" in your system is not a property of the=
=20
> type; it is a property of the object's value and the mechanism of=20
> relocation.
>
>
It is a property of the type. See all my explanations above.
@Hyman
Le vendredi 10 ao=C3=BBt 2018 22:19:37 UTC+2, Hyman Rosen a =C3=A9crit :
>
> On Fri, Aug 10, 2018 at 3:51 PM Nicol Bolas <jmck...@gmail.com> wrote:
>
>> OK, let's examine this idea in greater detail. You want to be able to=20
>> `realloc` and perform object fixup.
>>
>> So... what happens to the objects between `realloc` and object fixup?=20
>> What state are the objects in? What does the object model say about an=
=20
>> object in such a state? Can you access it? If so, with which operations?
>>
>> Furthermore, what exactly does "fix the objects" mean? How does a type g=
o=20
>> about doing that? What order are the subobjects in the object "fixed" in=
?=20
>> Who decides what this order is? Is this a user-defined process? And if "=
fix=20
>> the objects" involves running user-defined code, then what exactly can t=
hat=20
>> user-defined code do with the object?
>>
>
> It rather sounds like we need something like Ada's Adjust procedure for=
=20
> Controlled types:
> <https://www2.adacore.com/gap-static/GNAT_Book/html/aarm/AA-7-6.html>
>
I didn't know about that, but that looks really close to what I have,=20
indeed.=20
@Henry
Le vendredi 10 ao=C3=BBt 2018 22:39:48 UTC+2, Henry Miller a =C3=A9crit :=
=20
>
> On Fri, Aug 10, 2018, at 11:41 AM, floria...@gmail.com wrote:
>
> I was playing with memory allocations, what it is possible to do and how=
=20
> it is implemented.
> It made me think about relocations, so here is the result of my reflectio=
n.
>
>
> "Relocation" definition:
> An object is relocated when its address changes.
> This does not necessarily implies a copy of its bytes.
>
>
> When it can occur:
> This could happen if a call to realloc is performed.
> This could also happen as a compiler optimization
>
>
> What about memory compaction? This would be the most interesting and=20
> useful case to me. Memory fragmentation is an unfortunate reality that I=
=20
> sometimes fight.=20
>
I haven't thought about memory compaction.
What I have to say is: you would be able to realloc, so by realloc'ing your=
=20
objects, you should be able to reduce memory fragmentation, but reallocing=
=20
some object will not modify all the pointers pointing to those objects.
These would need some extra care.
=20
>
>
> How it can be integrated to the language:
> Relocation cannot be a constructor: no new object is created.
> Relocation cannot be an assignment operator: Only one object is involved.
>
> So here is what I propose:
> Every type has a relocation operator that takes a pointer and returning=
=20
> void (let's call it operator relocate to ease the explanation, but I have=
=20
> no strong opinion on the syntax).
> This operator is called just after the object address has changed (for=20
> whatever reason), and the pointer argument represents the old address of=
=20
> the object (which is now an invalid address).
>
> This operator can be deleted or defaulted.
> The operator relocate is trivial iif:
>
> - it is not user-provided (that is, it is implicitly-defined or=20
> defaulted)
> - T has no virtual member functions
> - T has no virtual base classes
> - the operator relocate selected for every direct base of T is trivial
> - the operator relocate selected for every non-static class type (or=
=20
> array of class type) member of T is trivial
> =20
> A trivial operator relocate is basically a noop.
>
>
> No syntax is proposed to call relocation (apart from object.operator=20
> relocate(p)).
>
>
> An operator relocate shall not change the state of the object if the new=
=20
> address is the same as the old address, even if the operator is not trivi=
al.
>
> It also cannot be virtual (you shall relocate only object through their=
=20
> true type).
>
>
> I propose that throwing relocation is allowed, but discouraged (but if=20
> this is problematic, I see no strong reason to keep throwing relocation).
>
>
> Small example:
>
>
>
> struct Bar;
> struct Foo {
> Bar* bar;
> };
>
> struct Bar {
> Foo* foo; // foo.bar is always equals to this
>
> Bar() : foo(new Foo{this}) {}
> ~Bar() {
> delete foo;
> }
>
> // copy is deleted
> Bar(const Bar&) =3D delete;
> Bar& operator=3D(const Bar&) =3D delete;
>
> // move needs to set the foo.bar to this object
> Bar(Bar&& other) : foo(other.foo) {
> other.foo =3D nullptr;
> foo.bar =3D this;
> }
> Bar& operator=3D(Bar&& other) {
> swap(foo, other.foo);
> foo.bar =3D this;
> other.foo.bar =3D &other;
> return *this;
> }
>
> // If address has changed, reset the foo.bar to point to the new=20
> location of the object
> void operator relocate(void*) {
> foo.bar =3D this;
> }
> };
>
>
>
> Your example code is undefined behavior. If some other thread access=20
> bar::foo after the reallocation and before bar::relocate gets to the fix =
up=20
> line your program goes boom.=20
>
The more I see it, the more I'm thinking that there is no other way around=
=20
the two steps (delocate/relocate).
Idea would be fairly simple: as soon as a thread has starting delocating an=
=20
object, accessing the object from other threads is UB.
Accessing the bytes of the the object will be fine, but only after=20
delocation has finished entirely (synchronisation will be needed).
Relocation would work the same in the opposite way: as soon as a thread=20
starts relocating an object from its bytes, the other threads will not be=
=20
able to access neither the object, nor its bytes.
As soon as the thread has finished relocating the object, it becomes=20
available for all threads (synchronisation also required here).
---- time ----->
*=3D=3D=3D=3D=3D=3D[delocate]**=3D=3D=3D=3D=3D=3D**[relocate]=3D=3D=3D=3D=
=3D=3D=3D*
*green*: all threads can access the object
*blue*: all threads can access the bytes of the object (not the object) and=
=20
copy/move them around
*red*: only the thread executing the delocation/relocation can access the=
=20
object/the bytes (might not be the same thread)
User code synchronisation is needed at the border of each region if one=20
wants to perform those tasks by different threads.
Also, that reminds me the if the same byte-sequence (from a single object)=
=20
is relocated twice, it would be UB.
(however, if two distinct delocated objects have the same byte-sequence,=20
then relocating this byte-sequence twice will be fine, but obviously, not a=
=20
third time)
=20
>
> That is the easiest way to show that this can't work. There are a large=
=20
> number of cases where you want to relocate an object that some other thre=
ad=20
> is accessing. The reality is that in modern CPUs threads are often the on=
ly=20
> way to get acceptable performance. This is why C++11 finally put threads=
=20
> into the object model. If you want to fall back to undefined behavior, th=
en=20
> you need to document exactly when things are undefined, show that there a=
re=20
> significant uses where you can use this without getting undefined behavio=
r,=20
> and make sure that "average person" has a reasonable chance of using it=
=20
> correctly.
>
>
see above (but you're right, it was missing).
=20
> I think that the only way this can work is if the object model has=20
> specific support for changing all pointers in an atomic way (this implies=
=20
> stop all threads before doing the reallocation, doing the fix up, then=20
> restarting threads). There are large performance considerations here, so =
it=20
> better be something that you don't pay for if you don't use.=20
>
>
I have the impression that you misunderstood what the fix up is:
If you have pointers to an object, and delocate this object: all pointers=
=20
to this object become invalid.
Those will not be magically fixed up when relocate is applied.
You would need to wrap all those pointer into a new object, and to write=20
the fixup code yourself.
Relocation fixes up only the objects managed by the relocated object.=20
Don't get me wrong, there are real problems that relocation support in the=
=20
> object model solves, but the problem is not easy.=20
>
I agree, that's not easy. But definitely worth a try.=20
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/5f1eb2f4-f7a2-46cb-955e-9080730fbd05%40isocpp.or=
g.
------=_Part_910_54720068.1533936173193
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>@Nicol<br>Le vendredi 10 ao=C3=BBt 2018 21:51:28 UTC+2=
, Nicol Bolas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div dir=3D"ltr"><br><br>On Friday, August 10, 2018 at 12:41:31 PM UTC-4=
, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr">I was playing with memory allocations, what it is possibl=
e to do and how it is implemented.<br>It made me think about relocations, s=
o here is the result of my reflection.<br><br><br><font size=3D"4">"Re=
location" definition:</font><br><div style=3D"margin-left:40px">An obj=
ect is relocated when its address changes.<br>This does not necessarily imp=
lies a copy of its bytes.<br></div><br></div></blockquote><div><br></div><d=
iv>This is where we run into a problem. The C++ object model is predicated =
on an object occupying a single region of storage throughout the period it =
exists:</div></div></blockquote><div><br></div><div>This doesn't change=
this view: an object cannot occupy more than one region. However, the regi=
on can be moved by some user code.</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid =
rgb(204,204,204);padding-left:1ex"><div>An object occupies a region of stor=
age in its period of construction (15.7), throughout its lifetime (6.8), an=
d in its period of destruction (15.7).<br></div></blockquote><div><br></div=
><div><i>Everything</i> about the C++ object model starts with this assumpt=
ion: objects live in a specific piece of storage. Change that, and you'=
re now rewriting the entire object model. The reason move in C++ was define=
d as constructing/assigning-with-<wbr>modification rather than what you'=
;re talking about was precisely to avoid having to do this.<br></div><div><=
br></div><div>The kind of thing you're talking about is a tremendous un=
dertaking. Your post barely scratches the surface of the implications of it=
.. If something like that is going to happen, you need a skilled spec-doctor=
/lawyer to take a look at whatever you're trying to do.</div><div><br><=
/div></div></blockquote><div><br></div><div>First, modifying the object mod=
el is fine, a big task, but fine if done right.</div><div>I will need help =
for sure, but I'm pretty sure it's worth a try.</div><div>And that&=
#39;s exactly why I posted this here. And your help is already welcomed ;)<=
br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr"><div></div><div></div><div>Furthermore, I find myself confused=
by these statements:</div><div><br></div><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);p=
adding-left:1ex"><div>Relocation might be called explicitly by user code, o=
r directly by the compiler as an optimization.</div><div><br></div><div>I d=
on't propose any situation where the language guarantees a relocation w=
ill happen.</div></blockquote><div><br></div><div>That seems contradictory.=
If users can explicitly perform relocation, then the langauge must be able=
to guarantee that there is some "situation" wherein "a relo=
cation will happen".</div><div><br></div></div></blockquote><div><br><=
/div><div>That's why I now think to have 2 operators: one to say the ob=
ject is not accessible but its bytes still are and can be copied/moved arou=
nd.</div><div>And the other to rematerialize the object from the bytes, eve=
n if the bytes have been moved.</div><div><br></div><div>So the situation w=
here a relocation will happen is bounded by these 2 operations. Every acces=
s to the object between these is UB, But accesses to the underlying bytes a=
re fine.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding=
-left:1ex"><div>Another optimization that can be done with such a relocatio=
n (and is not possible with any current form relocation/destructive move) i=
s to be able to std::realloc a buffer, and just fix the objects afterwards.=
<br></div></blockquote><div><br></div><div>OK, let's examine this idea =
in greater detail. You want to be able to `realloc` and perform object fixu=
p.</div><div><br></div><div>So... what happens to the objects between `real=
loc` and object fixup? What state are the objects in? What does the object =
model say about an object in such a state? Can you access it? If so, with w=
hich operations?<br></div></div></blockquote><div><br></div><div>First, let=
's replace realloc by delocate as I think it's much simpler to reas=
on about (a realloc could happen after delocate if you want).</div><div><br=
></div><div>So after a delocate, the object has no localisation: it is unre=
achable. The only way to make reachable (possibly at another address) it to=
relocate the same byte-sequence. Every accesses to the bytes directly are =
fine. (so reading might give some unspecified result?)<br></div><div>=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></=
div><div><br></div><div>Furthermore, what exactly does "fix the object=
s" mean? How does a type go about doing that? What order are the subob=
jects in the object "fixed" in? Who decides what this order is? I=
s this a user-defined process? And if "fix the objects" involves =
running user-defined code, then what exactly can that user-defined code do =
with the object?</div></div></blockquote><div><br></div><div>Fix the object=
means: the state before delocate and after relocate is the same. If you ca=
nnot guarantee that for your type, you should delete relocation.</div><div>=
<br></div><div>I think the order should not matter that much.</div><div>So =
I propose, for a compiler generated delocate, the same order as the destruc=
tor, and for relocate, the same order as constructor.<br></div><div><br></d=
iv><div>For a user-defined relocation, it's up to the user.</div><div><=
br></div><div>For a user defined relocation, I propose that all members are=
still accessible until the end of the delocate operator (allows to skip so=
me delocation code of some members if you know it's fine).</div><div>An=
d for relocation, all objects are accessible from the start of the relocate=
operator (identically, you could skip relocation of some members).</div><d=
iv>As all fundamental types are trivially relocatable, that's fine.</di=
v><div>Within those two operators, rules are the same as elsewhere. You wou=
ld just need to be careful as some pointers might point to the old storage,=
so shouldn't be dereferenced, but this is not a special rule.<br></div=
><div><br></div><div>That makes me think that a struct with references shou=
ld not be relocatable as you cannot rebind a reference.</div><div><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; bord=
er-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>Other issue=
s:<br><br>If you have to "fix the object" after a non-copying, ad=
dress changing `realloc`, wouldn't it be faster to just do a memcpy? If=
every pointer subobject may have to have some fixup work done based on whe=
re it points to and the realloced range of memory, doesn't that mean th=
at you're going to touch every cache line in that range? OK sure, you d=
on't have to allocate new pages of memory and copy to that memory, but =
aren't there efficient ways to handle that?<br></div></blockquote><div>=
<br></div><div>If you do a memcpy, you still need the fixup step.<br></div>=
<div>How can newpages+memcpy+fixup being faster than fixup only?</div><div>=
<br></div><div>Also, pointers are trivially relocatable: if you have a poin=
ter relocate it, the value of the pointer will not change. If the pointer p=
oints within the realloc'ed region, then your relocate operators are pr=
obably wrong.</div><div><br></div><div>The fastest way to allocate new page=
s and copy the content from the previous pages is to create a copy-on-write=
shared pages. I'm not sure how easy it is do that after you have alloc=
ated the pages the first time.<br></div><div>But that doesn't really ch=
ange the issue, does it?<br></div><div>=C2=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(20=
4, 204, 204); padding-left: 1ex;"><div><br>And either way, the operation is=
O(n) for any types that aren't trivially relocatable. Since "fix =
the objects" has to happen for each object in the range. So `vector<=
;T>` would only be able to have O(1) reallocation if the objects are tri=
vially relocatable.<br></div></blockquote><div><br></div><div>First, growin=
g a vector for non trivially relocatable types will remain amortized O(1). =
But even then, I think it can still benefit from relocation as you will nee=
d to modify only a few part of your objects.<br></div><div>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-le=
ft: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><br>Also, I thin=
k you overestimate how broad "trivially relocatable" types under =
your definition will be. Any type with a pointer as a subobject cannot be t=
rivially relocatable, since you may need pointer fixup when you relocate it=
.. `unique_ptr<T>` cannot be trivially relocatable, because you don=
9;t know if it points to something that was relocated with it.<br></div></b=
lockquote><div><br></div><div>You underestimate what trivially relocatable =
is: a pointer is trivially relocatable.</div><div>After a call to delocate,=
every pointers to the object are invalidated and should not be accessed as=
objects, can only be accessed as bytes.</div><div>Like that, if you try to=
relocate the content of the unique_ptr, the pointer within unique_ptr will=
be invalidated, thus will be undefined behavior.</div><div><br></div><div>=
In short, you cannot relocate the objects of a unique_ptr at the same time =
as the unique_ptr itself.</div><div>If you want to do that (because you hav=
e a total control on how the unique_ptr does its allocations), you would ne=
ed to wrap the unique_ptr into another object, and write this other object =
relocation in the way you want.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid=
rgb(204, 204, 204); padding-left: 1ex;"><div><br>That is, "trivially =
relocatable" in your system is not a property of the type; it is a pro=
perty of the object's value and the mechanism of relocation.<br><br></d=
iv></blockquote><div><br></div><div>It is a property of the type. See all m=
y explanations above.<br></div><div><br></div><br>@Hyman<br>Le vendredi 10 =
ao=C3=BBt 2018 22:19:37 UTC+2, Hyman Rosen a =C3=A9crit=C2=A0:<blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div class=3D"gmail_quote"=
><div dir=3D"ltr">On Fri, Aug 10, 2018 at 3:51 PM Nicol Bolas <<a target=
=3D"_blank" rel=3D"nofollow">jmck...@gmail.com</a>> wrote:</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px=
solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>OK, let'=
;s examine this idea in greater detail. You want to be able to `realloc` an=
d perform object fixup.</div><div><br></div><div>So...
what happens to the objects between `realloc` and object fixup? What=20
state are the objects in? What does the object model say about an object
in such a state? Can you access it? If so, with which operations?<br></div=
><div><br></div><div>Furthermore,
what exactly does "fix the objects" mean? How does a type go abo=
ut=20
doing that? What order are the subobjects in the object "fixed" i=
n? Who=20
decides what this order is? Is this a user-defined process? And if "fi=
x=20
the objects" involves running user-defined code, then what exactly can=
=20
that user-defined code do with the object?<br></div></div></blockquote><div=
><br>It rather sounds like we need something like Ada's Adjust procedur=
e for Controlled types:<br><<a href=3D"https://www2.adacore.com/gap-stat=
ic/GNAT_Book/html/aarm/AA-7-6.html" target=3D"_blank" rel=3D"nofollow">http=
s://www2.adacore.com/gap-<wbr>static/GNAT_Book/html/aarm/AA-<wbr>7-6.html</=
a>></div></div></div></blockquote><div><br></div><div>I didn't know =
about that, but that looks really close to what I have, indeed. <br></div><=
div><br></div><div><br></div><div>@Henry<br>Le vendredi 10 ao=C3=BBt 2018 2=
2:39:48 UTC+2, Henry Miller a =C3=A9crit=C2=A0:
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; borde=
r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>On Fri, Aug =
10, 2018, at 11:41 AM, <a target=3D"_blank" rel=3D"nofollow">floria...@gmai=
l.com</a> wrote:<br></div><blockquote type=3D"cite"><div dir=3D"ltr"><div s=
tyle=3D"font-family:Arial">I was playing with memory allocations, what it i=
s possible to do and how it is implemented.<br></div>
<div style=3D"font-family:Arial">It made me think about relocations, so her=
e is the result of my reflection.<br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">"Relo=
cation" definition:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">An object =
is relocated when its address changes.<br></div>
<div style=3D"font-family:Arial">This does not necessarily implies a copy o=
f its bytes.<br></div>
</div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">When it ca=
n occur:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">This could=
happen if a call to realloc is performed.<br></div>
<div style=3D"font-family:Arial">This could also happen as a compiler optim=
ization<br></div>
</div>
</div>
</blockquote><div style=3D"font-family:Arial"><br></div><div style=3D"font-=
family:Arial">What about memory compaction? This would=20
be the most interesting and useful case to me. Memory fragmentation is=20
an unfortunate reality that I sometimes fight.=C2=A0</div></blockquote><div=
><br></div><div>I haven't thought about memory compaction.</div><div>Wh=
at I have to say is: you would be able to realloc, so by realloc'ing yo=
ur objects, you should be able to reduce memory fragmentation, but realloci=
ng some object will not modify all the pointers pointing to those objects.<=
/div><div>These would need some extra care.<br></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-lef=
t: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div style=3D"font-fam=
ily:Arial"><br></div><blockquote type=3D"cite"><div dir=3D"ltr"><div style=
=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">How it can=
be integrated to the language:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">Relocation=
cannot be a constructor: no new object is created.<br></div>
<div style=3D"font-family:Arial">Relocation cannot be an assignment operato=
r: Only one object is involved.<br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">So here is what I propose:<br></div>
<div style=3D"font-family:Arial">Every type has a relocation operator that =
takes a pointer and returning <span style=3D"font-family:"courier new&=
quot;,monospace">void</span> (let's call it <span style=3D"font-family:=
"courier new",monospace">operator relocate</span> to ease the exp=
lanation, but I have no strong opinion on the syntax).<br></div>
<div style=3D"font-family:Arial">This operator is called just after the=20
object address has changed (for whatever reason), and the pointer=20
argument represents the old address of the object (which is now an=20
invalid address).<br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">This operator can be deleted or defaulted.=
<br></div>
<div style=3D"font-family:Arial">The <span style=3D"font-family:"couri=
er new",monospace">operator relocate</span> is trivial iif:<br></div>
</div>
<ul style=3D"margin-left:40px"><li>it is not user-provided (that is, it is =
implicitly-defined or defaulted)<span><span></span></span><br></li><li><cod=
e>T</code> has no virtual member functions<br></li><li><code>T</code> has n=
o virtual base classes<br></li><li>the <span style=3D"font-family:"cou=
rier new",monospace">operator relocate</span> selected for every direc=
t base of <code>T</code> is trivial<br></li><li>the <span style=3D"font-fam=
ily:"courier new",monospace">operator relocate</span> selected fo=
r every non-static class type (or array of class type) member of <code>T</c=
ode> is trivial<br></li></ul><p style=3D"margin-left:40px">A trivial <span =
style=3D"font-family:"courier new",monospace">operator relocate</=
span> is basically a noop.<br></p><p style=3D"margin-left:40px"><br></p><p =
style=3D"margin-left:40px">No syntax is proposed to call relocation (apart =
from <span style=3D"font-family:"courier new",monospace">object.o=
perator relocate(p)</span>).<br></p><p style=3D"margin-left:40px"><br></p><=
p style=3D"margin-left:40px">An <span style=3D"font-family:"courier ne=
w",monospace">operator relocate</span>
shall not change the state of the object if the new address is the same
as the old address, even if the operator is not trivial.<br></p><p style=
=3D"margin-left:40px">It also cannot be virtual (you shall relocate only ob=
ject through their true type).<br></p><p style=3D"margin-left:40px"><br></p=
><p style=3D"margin-left:40px">I
propose that throwing relocation is allowed, but discouraged (but if=20
this is problematic, I see no strong reason to keep throwing=20
relocation).<br></p><p><br></p><p><span style=3D"font-size:large">Small exa=
mple:</span><br></p><p style=3D"margin-left:40px"><br></p><div style=3D"bac=
kground-color:rgb(250,250,250);border-top-color:rgb(187,187,187);border-rig=
ht-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-=
color:rgb(187,187,187);border-top-style:solid;border-right-style:solid;bord=
er-bottom-style:solid;border-left-style:solid;border-top-width:1px;border-r=
ight-width:1px;border-bottom-width:1px;border-left-width:1px"><div style=3D=
"font-family:Arial"><code></code><br></div>
<div><code><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><sp=
an style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)">=
<br></span><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Foo</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"c=
olor:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">*</span=
><span style=3D"color:rgb(0,0,0)"> bar</span><span style=3D"color:rgb(102,1=
02,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"c=
olor:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br><br></sp=
an><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb=
(102,0,102)">Foo</span><span style=3D"color:rgb(102,102,0)">*</span><span s=
tyle=3D"color:rgb(0,0,0)"> foo</span><span style=3D"color:rgb(102,102,0)">;=
</span><span style=3D"color:rgb(0,0,0)"> // foo.bar is always equals to thi=
s<br><br>=C2=A0 </span><span style=3D"color:rgb(102,0,102)">Bar</span><span=
style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rg=
b(0,0,0)"> foo</span><span style=3D"color:rgb(102,102,0)">(</span><span sty=
le=3D"color:rgb(0,0,136)">new</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,0,102)">Foo</span><span style=3D"color:rgb(1=
02,102,0)">{</span><span style=3D"color:rgb(0,0,136)">this</span><span styl=
e=3D"color:rgb(102,102,0)">})</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,102,0)">{}</span><span style=3D"color:rgb(0,=
0,0)"><code><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=
=3D"color:rgb(102,102,0)">~</span><span style=3D"color:rgb(102,0,102)">Bar<=
/span><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0=
,136)">delete</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=
=A0 </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"colo=
r:rgb(0,0,0)"><br></span></code><br>=C2=A0 // copy is deleted<br>=C2=A0 </s=
pan><span style=3D"color:rgb(102,0,102)">Bar</span><span style=3D"color:rgb=
(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">const</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar<=
/span><span style=3D"color:rgb(102,102,0)">&)</span><span style=3D"colo=
r:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delet=
e</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:r=
gb(0,0,0)"><code><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span s=
tyle=3D"color:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)=
">&</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(0,0,136)">operator</span><span style=3D"color:rgb(102,102,0)">=3D(</sp=
an><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=
=3D"color:rgb(102,102,0)">&)</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delete</span><span sty=
le=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br><b=
r>=C2=A0 // move needs to set the foo.bar to this object<br></span></code>=
=C2=A0 </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=3D=
"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">Bar</sp=
an><span style=3D"color:rgb(102,102,0)">&&</span><span style=3D"col=
or:rgb(0,0,0)"> other</span><span style=3D"color:rgb(102,102,0)">)</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"=
>:</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=3D"color:r=
gb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">other</span><span s=
tyle=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo<=
/span><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 other</span><span style=3D"color:rg=
b(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo </span><span sty=
le=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(0,0,136)">nullptr</span><span style=3D"color:r=
gb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 f=
oo</span><span style=3D"color:rgb(102,102,0)">.</span><span style=3D"color:=
rgb(0,0,0)">bar </span><span style=3D"color:rgb(102,102,0)">=3D</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">this=
</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102,0)">}</span><s=
pan style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(1=
02,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">&</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">oper=
ator</span><span style=3D"color:rgb(102,102,0)">=3D(</span><span style=3D"c=
olor:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">&&a=
mp;</span><span style=3D"color:rgb(0,0,0)"> other</span><span style=3D"colo=
r:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 =C2=A0 swap</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(0,0,0)">foo</span><span style=3D"color:rgb(102,102,0)">=
,</span><span style=3D"color:rgb(0,0,0)"> other</span><span style=3D"color:=
rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo</span><span st=
yle=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 =C2=A0 foo</span><span style=3D"color:rgb(102,102,0)">.</span><span =
style=3D"color:rgb(0,0,0)">bar </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 other</span><span style=3D"color=
:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo</span><span s=
tyle=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">bar =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">&</span><span =
style=3D"color:rgb(0,0,0)">other</span><span style=3D"color:rgb(102,102,0)"=
>;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 </span><span st=
yle=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb=
(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102=
,0)">}</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 // If address =
has changed, reset the foo.bar to point to the new location of the object<b=
r>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">void</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">operator</=
span><span style=3D"color:rgb(0,0,0)"> relocate</span><span style=3D"color:=
rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">void</span><span=
style=3D"color:rgb(102,102,0)">*)</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color:rgb(102,102,0)">=
..</span><span style=3D"color:rgb(0,0,0)">bar </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span styl=
e=3D"color:rgb(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;<=
/span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"col=
or:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)">=
</span></code></div>
<div style=3D"font-family:Arial"><code></code><br></div>
</div>
<p><br></p></div>
</blockquote><div style=3D"font-family:Arial"><br></div><div style=3D"font-=
family:Arial">Your example code is undefined behavior.=20
If some other thread access bar::foo after the reallocation and before=20
bar::relocate gets to the fix up line your program goes boom.=C2=A0<br></di=
v></blockquote><div><br></div><div>The more I see it, the more I'm thin=
king that there is no other way around the two steps (delocate/relocate).</=
div><div><br></div><div>Idea would be fairly simple: as soon as a thread ha=
s starting delocating an object, accessing the object from other threads is=
UB.</div><div>Accessing the bytes of the the object will be fine, but only=
after delocation has finished entirely (synchronisation will be needed).</=
div><div><br></div><div>Relocation would work the same in the opposite way:=
as soon as a thread starts relocating an object from its bytes, the other =
threads will not be able to access neither the object, nor its bytes.</div>=
<div>As soon as the thread has finished relocating the object, it becomes a=
vailable for all threads (synchronisation also required here).<br></div><di=
v><br></div><div>---- time -----><br></div><div><b><span style=3D"color:=
rgb(56, 118, 29);">=3D=3D=3D=3D=3D=3D</span><span style=3D"color: rgb(153,=
0, 0);">[delocate]</span></b><span style=3D"color: rgb(0, 0, 255);"><b>=3D=
=3D=3D=3D=3D=3D</b></span><b><span style=3D"color: rgb(153, 0, 0);">[reloca=
te]</span><span style=3D"color: rgb(56, 118, 29);">=3D=3D=3D=3D=3D=3D=3D</s=
pan></b><br></div><div><b><span style=3D"color: rgb(56, 118, 29);">green</s=
pan></b>: all threads can access the object</div><div><b><span style=3D"col=
or: rgb(0, 0, 255);">blue</span></b>: all threads can access the bytes of t=
he object (not the object) and copy/move them around<br></div><div><b><span=
style=3D"color: rgb(153, 0, 0);">red</span></b>: only the thread executing=
the delocation/relocation can access the object/the bytes (might not be th=
e same thread)<br></div><div>User code synchronisation is needed at the bor=
der of each region if one wants to perform those tasks by different threads=
..<br></div><div><br></div><div>Also, that reminds me the if the same byte-s=
equence (from a single object) is relocated twice, it would be UB.</div><di=
v>(however, if two distinct delocated objects have the same byte-sequence, =
then relocating this byte-sequence twice will be fine, but obviously, not a=
third time)<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204)=
; padding-left: 1ex;"><div style=3D"font-family:Arial"></div><div style=3D"=
font-family:Arial"><br></div><div style=3D"font-family:Arial">That is the e=
asiest way to show that this
can't work. There are a large number of cases where you want to=20
relocate an object that some other thread is accessing. The reality is=20
that in modern CPUs threads are often the only way to get acceptable=20
performance. This is why C++11 finally put threads into the object=20
model. If you want to fall back to undefined behavior, then you need to=20
document exactly when things are undefined, show that there are=20
significant uses where you can use this without getting undefined=20
behavior, and make sure that "average person" has a reasonable ch=
ance of
using it correctly.<br></div><div style=3D"font-family:Arial"><br></div></=
blockquote><div><br></div><div>see above (but you're right, it was miss=
ing).<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); paddi=
ng-left: 1ex;"><div style=3D"font-family:Arial"></div><div style=3D"font-fa=
mily:Arial">I think that the only way this can work=20
is if the object model has specific support for changing all pointers in
an atomic way (this implies stop all threads before doing the=20
reallocation, doing the fix up, then restarting threads). There are=20
large performance considerations here, so it better be something that=20
you don't pay for if you don't use.=C2=A0<br></div><div style=3D"fo=
nt-family:Arial"><br></div></blockquote><div><br></div><div>I have the impr=
ession that you misunderstood what the fix up is:</div><div>If you have poi=
nters to an object, and delocate this object: all pointers to this object b=
ecome invalid.</div><div>Those will not be magically fixed up when relocate=
is applied.</div><div>You would need to wrap all those pointer into a new =
object, and to write the fixup code yourself.</div><div><br></div><div>Relo=
cation fixes up only the objects managed by the relocated object. <br></div=
><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><=
div style=3D"font-family:Arial"></div><div style=3D"font-family:Arial">Don&=
#39;t get me wrong, there are real problems that relocation support in the =
object model solves, but the problem is not easy. <br></div></blockquote><d=
iv><br></div><div>I agree, that's not easy. But definitely worth a try.=
<br></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5f1eb2f4-f7a2-46cb-955e-9080730fbd05%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5f1eb2f4-f7a2-46cb-955e-9080730fbd05=
%40isocpp.org</a>.<br />
------=_Part_910_54720068.1533936173193--
------=_Part_909_591342614.1533936173191--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 10 Aug 2018 14:25:33 -0700 (PDT)
Raw View
------=_Part_920_1203399263.1533936333382
Content-Type: multipart/alternative;
boundary="----=_Part_921_242881540.1533936333383"
------=_Part_921_242881540.1533936333383
Content-Type: text/plain; charset="UTF-8"
On Friday, August 10, 2018 at 4:39:48 PM UTC-4, Henry Miller wrote:
>
> On Fri, Aug 10, 2018, at 11:41 AM, floria...@gmail.com <javascript:>
> wrote:
>
> I was playing with memory allocations, what it is possible to do and how
> it is implemented.
> It made me think about relocations, so here is the result of my reflection.
>
>
> "Relocation" definition:
> An object is relocated when its address changes.
> This does not necessarily implies a copy of its bytes.
>
>
> When it can occur:
> This could happen if a call to realloc is performed.
> This could also happen as a compiler optimization
>
>
> What about memory compaction? This would be the most interesting and
> useful case to me. Memory fragmentation is an unfortunate reality that I
> sometimes fight.
>
>
> How it can be integrated to the language:
> Relocation cannot be a constructor: no new object is created.
> Relocation cannot be an assignment operator: Only one object is involved.
>
> So here is what I propose:
> Every type has a relocation operator that takes a pointer and returning
> void (let's call it operator relocate to ease the explanation, but I have
> no strong opinion on the syntax).
> This operator is called just after the object address has changed (for
> whatever reason), and the pointer argument represents the old address of
> the object (which is now an invalid address).
>
> This operator can be deleted or defaulted.
> The operator relocate is trivial iif:
>
> - it is not user-provided (that is, it is implicitly-defined or
> defaulted)
> - T has no virtual member functions
> - T has no virtual base classes
> - the operator relocate selected for every direct base of T is trivial
> - the operator relocate selected for every non-static class type (or
> array of class type) member of T is trivial
>
> A trivial operator relocate is basically a noop.
>
>
> No syntax is proposed to call relocation (apart from object.operator
> relocate(p)).
>
>
> An operator relocate shall not change the state of the object if the new
> address is the same as the old address, even if the operator is not trivial.
>
> It also cannot be virtual (you shall relocate only object through their
> true type).
>
>
> I propose that throwing relocation is allowed, but discouraged (but if
> this is problematic, I see no strong reason to keep throwing relocation).
>
>
> Small example:
>
>
>
> struct Bar;
> struct Foo {
> Bar* bar;
> };
>
> struct Bar {
> Foo* foo; // foo.bar is always equals to this
>
> Bar() : foo(new Foo{this}) {}
> ~Bar() {
> delete foo;
> }
>
> // copy is deleted
> Bar(const Bar&) = delete;
> Bar& operator=(const Bar&) = delete;
>
> // move needs to set the foo.bar to this object
> Bar(Bar&& other) : foo(other.foo) {
> other.foo = nullptr;
> foo.bar = this;
> }
> Bar& operator=(Bar&& other) {
> swap(foo, other.foo);
> foo.bar = this;
> other.foo.bar = &other;
> return *this;
> }
>
> // If address has changed, reset the foo.bar to point to the new
> location of the object
> void operator relocate(void*) {
> foo.bar = this;
> }
> };
>
>
>
> Your example code is undefined behavior. If some other thread access
> bar::foo after the reallocation and before bar::relocate gets to the fix up
> line your program goes boom.
>
How would that be different from any other data race? Presumably,
relocating an object is accessing it. So if two threads are accessing the
same object at the same time, it's a data race: UB.
If you need to thread relocation with other accesses, it should be on you
to provide it. Even atomic pointer fixup operation wouldn't be enough,
because you can have more than one pointer in an object to fix up.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6acf3e14-579e-45d4-9a6f-9a548adf2c08%40isocpp.org.
------=_Part_921_242881540.1533936333383
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, August 10, 2018 at 4:39:48 PM UTC-4, Henry Mill=
er wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div><div>On Fri, Aug 10, 2018, at 11:41 AM, <a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"xe-X0qBXDQAJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">floria...@gmail.com</a> wrote:<br><=
/div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial"=
>I was playing with memory allocations, what it is possible to do and how i=
t is implemented.<br></div>
<div style=3D"font-family:Arial">It made me think about relocations, so her=
e is the result of my reflection.<br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">"Relo=
cation" definition:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">An object =
is relocated when its address changes.<br></div>
<div style=3D"font-family:Arial">This does not necessarily implies a copy o=
f its bytes.<br></div>
</div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">When it ca=
n occur:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">This could=
happen if a call to realloc is performed.<br></div>
<div style=3D"font-family:Arial">This could also happen as a compiler optim=
ization<br></div>
</div>
</div>
</blockquote><div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">What about memory compaction? This would b=
e the most interesting and useful case to me. Memory fragmentation is an un=
fortunate reality that I sometimes fight.=C2=A0</div>
<div style=3D"font-family:Arial"><br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial"=
><br></div>
<div style=3D"font-family:Arial"><span style=3D"font-size:large">How it can=
be integrated to the language:</span><br></div>
<div style=3D"margin-left:40px"><div style=3D"font-family:Arial">Relocation=
cannot be a constructor: no new object is created.<br></div>
<div style=3D"font-family:Arial">Relocation cannot be an assignment operato=
r: Only one object is involved.<br></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">So here is what I propose:<br></div>
<div style=3D"font-family:Arial">Every type has a relocation operator that =
takes a pointer and returning <span style=3D"font-family:"courier new&=
quot;,monospace">void</span> (let's call it <span style=3D"font-family:=
"courier new",monospace">operator relocate</span> to ease the exp=
lanation, but I have no strong opinion on the syntax).<br></div>
<div style=3D"font-family:Arial">This operator is called just after the obj=
ect address has changed (for whatever reason), and the pointer argument rep=
resents the old address of the object (which is now an invalid address).<br=
></div>
<div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">This operator can be deleted or defaulted.=
<br></div>
<div style=3D"font-family:Arial">The <span style=3D"font-family:"couri=
er new",monospace">operator relocate</span> is trivial iif:<br></div>
</div>
<ul style=3D"margin-left:40px"><li>it is not user-provided (that is, it is =
implicitly-defined or defaulted)<span><span></span></span><br></li><li><cod=
e>T</code> has no virtual member functions<br></li><li><code>T</code> has n=
o virtual base classes<br></li><li>the <span style=3D"font-family:"cou=
rier new",monospace">operator relocate</span> selected for every direc=
t base of <code>T</code> is trivial<br></li><li>the <span style=3D"font-fam=
ily:"courier new",monospace">operator relocate</span> selected fo=
r every non-static class type (or array of class type) member of <code>T</c=
ode> is trivial<br></li></ul><p style=3D"margin-left:40px">A trivial <span =
style=3D"font-family:"courier new",monospace">operator relocate</=
span> is basically a noop.<br></p><p style=3D"margin-left:40px"><br></p><p =
style=3D"margin-left:40px">No syntax is proposed to call relocation (apart =
from <span style=3D"font-family:"courier new",monospace">object.o=
perator relocate(p)</span>).<br></p><p style=3D"margin-left:40px"><br></p><=
p style=3D"margin-left:40px">An <span style=3D"font-family:"courier ne=
w",monospace">operator relocate</span> shall not change the state of t=
he object if the new address is the same as the old address, even if the op=
erator is not trivial.<br></p><p style=3D"margin-left:40px">It also cannot =
be virtual (you shall relocate only object through their true type).<br></p=
><p style=3D"margin-left:40px"><br></p><p style=3D"margin-left:40px">I prop=
ose that throwing relocation is allowed, but discouraged (but if this is pr=
oblematic, I see no strong reason to keep throwing relocation).<br></p><p><=
br></p><p><span style=3D"font-size:large">Small example:</span><br></p><p s=
tyle=3D"margin-left:40px"><br></p><div style=3D"background-color:rgb(250,25=
0,250);border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187=
);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);b=
order-top-style:solid;border-right-style:solid;border-bottom-style:solid;bo=
rder-left-style:solid;border-top-width:1px;border-right-width:1px;border-bo=
ttom-width:1px;border-left-width:1px"><div style=3D"font-family:Arial"><cod=
e></code><br></div>
<div><code><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><sp=
an style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)">=
<br></span><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Foo</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"c=
olor:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">*</span=
><span style=3D"color:rgb(0,0,0)"> bar</span><span style=3D"color:rgb(102,1=
02,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"c=
olor:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br><br></sp=
an><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span>=
<span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb=
(102,0,102)">Foo</span><span style=3D"color:rgb(102,102,0)">*</span><span s=
tyle=3D"color:rgb(0,0,0)"> foo</span><span style=3D"color:rgb(102,102,0)">;=
</span><span style=3D"color:rgb(0,0,0)"> // foo.bar is always equals to thi=
s<br><br>=C2=A0 </span><span style=3D"color:rgb(102,0,102)">Bar</span><span=
style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rg=
b(0,0,0)"> foo</span><span style=3D"color:rgb(102,102,0)">(</span><span sty=
le=3D"color:rgb(0,0,136)">new</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,0,102)">Foo</span><span style=3D"color:rgb(1=
02,102,0)">{</span><span style=3D"color:rgb(0,0,136)">this</span><span styl=
e=3D"color:rgb(102,102,0)">})</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,102,0)">{}</span><span style=3D"color:rgb(0,=
0,0)"><code><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=
=3D"color:rgb(102,102,0)">~</span><span style=3D"color:rgb(102,0,102)">Bar<=
/span><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0=
,136)">delete</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=
=A0 </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"colo=
r:rgb(0,0,0)"><br></span></code><br>=C2=A0 // copy is deleted<br>=C2=A0 </s=
pan><span style=3D"color:rgb(102,0,102)">Bar</span><span style=3D"color:rgb=
(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">const</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar<=
/span><span style=3D"color:rgb(102,102,0)">&)</span><span style=3D"colo=
r:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delet=
e</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:r=
gb(0,0,0)"><code><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span s=
tyle=3D"color:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)=
">&</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(0,0,136)">operator</span><span style=3D"color:rgb(102,102,0)">=3D(</sp=
an><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=
=3D"color:rgb(102,102,0)">&)</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delete</span><span sty=
le=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br><b=
r>=C2=A0 // move needs to set the foo.bar to this object<br></span></code>=
=C2=A0 </span><span style=3D"color:rgb(102,0,102)">Bar</span><span style=3D=
"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">Bar</sp=
an><span style=3D"color:rgb(102,102,0)">&&</span><span style=3D"col=
or:rgb(0,0,0)"> other</span><span style=3D"color:rgb(102,102,0)">)</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"=
>:</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=3D"color:r=
gb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">other</span><span s=
tyle=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo<=
/span><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 other</span><span style=3D"color:rg=
b(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo </span><span sty=
le=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(0,0,136)">nullptr</span><span style=3D"color:r=
gb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 f=
oo</span><span style=3D"color:rgb(102,102,0)">.</span><span style=3D"color:=
rgb(0,0,0)">bar </span><span style=3D"color:rgb(102,102,0)">=3D</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">this=
</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102,0)">}</span><s=
pan style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(1=
02,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">&</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">oper=
ator</span><span style=3D"color:rgb(102,102,0)">=3D(</span><span style=3D"c=
olor:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,102,0)">&&a=
mp;</span><span style=3D"color:rgb(0,0,0)"> other</span><span style=3D"colo=
r:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 =C2=A0 swap</span><span style=3D"color:rgb(102,102,0)">(</span><span=
style=3D"color:rgb(0,0,0)">foo</span><span style=3D"color:rgb(102,102,0)">=
,</span><span style=3D"color:rgb(0,0,0)"> other</span><span style=3D"color:=
rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo</span><span st=
yle=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 =C2=A0 foo</span><span style=3D"color:rgb(102,102,0)">.</span><span =
style=3D"color:rgb(0,0,0)">bar </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 other</span><span style=3D"color=
:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">foo</span><span s=
tyle=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">bar =
</span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">&</span><span =
style=3D"color:rgb(0,0,0)">other</span><span style=3D"color:rgb(102,102,0)"=
>;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 </span><span st=
yle=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb=
(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102=
,0)">}</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 // If address =
has changed, reset the foo.bar to point to the new location of the object<b=
r>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">void</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">operator</=
span><span style=3D"color:rgb(0,0,0)"> relocate</span><span style=3D"color:=
rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">void</span><span=
style=3D"color:rgb(102,102,0)">*)</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 =C2=A0 foo</span><span style=3D"color:rgb(102,102,0)">=
..</span><span style=3D"color:rgb(0,0,0)">bar </span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span styl=
e=3D"color:rgb(0,0,136)">this</span><span style=3D"color:rgb(102,102,0)">;<=
/span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"col=
or:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span><spa=
n style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)">=
</span></code></div>
<div style=3D"font-family:Arial"><code></code><br></div>
</div>
<p><br></p></div>
</blockquote><div style=3D"font-family:Arial"><br></div>
<div style=3D"font-family:Arial">Your example code is undefined behavior. I=
f some other thread access bar::foo after the reallocation and before bar::=
relocate gets to the fix up line your program goes boom.<br></div></div></b=
lockquote><div><br></div><div>How would that be different from any other da=
ta race? Presumably, relocating an object is accessing it. So if two thread=
s are accessing the same object at the same time, it's a data race: UB.=
<br></div><div><br></div><div>If you need to thread relocation with other a=
ccesses, it should be on you to provide it. Even atomic pointer fixup opera=
tion wouldn't be enough, because you can have more than one pointer in =
an object to fix up.<br></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6acf3e14-579e-45d4-9a6f-9a548adf2c08%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6acf3e14-579e-45d4-9a6f-9a548adf2c08=
%40isocpp.org</a>.<br />
------=_Part_921_242881540.1533936333383--
------=_Part_920_1203399263.1533936333382--
.
Author: Henry Miller <hank@millerfarm.com>
Date: Fri, 10 Aug 2018 17:05:08 -0500
Raw View
This is a multi-part message in MIME format.
--_----------=_15339387089213350
Content-Type: text/plain; charset="UTF-8"
On Fri, Aug 10, 2018, at 4:25 PM, Nicol Bolas wrote:
> On Friday, August 10, 2018 at 4:39:48 PM UTC-4, Henry Miller wrote:
>> On Fri, Aug 10, 2018, at 11:41 AM, floria...@gmail.com wrote:
>>> I was playing with memory allocations, what it is possible to do and
>>> how it is implemented.>>> It made me think about relocations, so here is the result of my
>>> reflection.>>>
>>>
>>> "Relocation" definition:
>>> An object is relocated when its address changes.
>>> This does not necessarily implies a copy of its bytes.
>>>
>>>
>>> When it can occur:
>>> This could happen if a call to realloc is performed.
>>> This could also happen as a compiler optimization
>>
>> What about memory compaction? This would be the most interesting and
>> useful case to me. Memory fragmentation is an unfortunate reality
>> that I sometimes fight.>>
>>>
>>> How it can be integrated to the language:
>>> Relocation cannot be a constructor: no new object is created.
>>> Relocation cannot be an assignment operator: Only one object is
>>> involved.>>>
>>> So here is what I propose:
>>> Every type has a relocation operator that takes a pointer and
>>> returning void (let's call it operator relocate to ease the
>>> explanation, but I have no strong opinion on the syntax).>>> This operator is called just after the object address has changed
>>> (for whatever reason), and the pointer argument represents the old
>>> address of the object (which is now an invalid address).>>>
>>> This operator can be deleted or defaulted.
>>> The operator relocate is trivial iif:
>>> * it is not user-provided (that is, it is implicitly-defined or
>>> defaulted)
>>> * T has no virtual member functions
>>> * T has no virtual base classes
>>> * the operator relocate selected for every direct base of T is
>>> trivial
>>> * the operator relocate selected for every non-static class type
>>> (or array of class type) member of T is trivial>>> A trivial operator relocate is basically a noop.
>>>
>>> No syntax is proposed to call relocation (apart from object.operator
>>> relocate(p)).>>>
>>> An operator relocate shall not change the state of the object if the
>>> new address is the same as the old address, even if the operator is
>>> not trivial.>>> It also cannot be virtual (you shall relocate only object through
>>> their true type).>>>
>>> I propose that throwing relocation is allowed, but discouraged (but
>>> if this is problematic, I see no strong reason to keep throwing
>>> relocation).>>>
>>> Small example:
>>>
>>>
>>> struct Bar; struct Foo { Bar* bar; };
>>>
>>> struct Bar { Foo* foo; // foo.bar is always equals to this
>>>
>>> Bar() : foo(new Foo{this}) {} ~Bar() { delete foo; }
>>>
>>> // copy is deleted Bar(const Bar&) = delete; Bar& operator=(const
>>> Bar&) = delete;
>>>
>>> // move needs to set the foo.bar to this object Bar(Bar&& other) :
>>> foo(other.foo) { other.foo = nullptr; foo.bar = this; } Bar&
>>> operator=(Bar&& other) { swap(foo, other.foo); foo.bar = this;
>>> other.foo.bar = &other; return *this; }
>>>
>>> // If address has changed, reset the foo.bar to point to the new
>>> location of the object void operator relocate(void*) { foo.bar =
>>> this; } };>>>
>>>
>>
>> Your example code is undefined behavior. If some other thread access
>> bar::foo after the reallocation and before bar::relocate gets to the
>> fix up line your program goes boom.>
> How would that be different from any other data race? Presumably,
> relocating an object is accessing it. So if two threads are accessing
> the same object at the same time, it's a data race: UB.>
> If you need to thread relocation with other accesses, it should be
> on you to provide it. Even atomic pointer fixup operation wouldn't
> be enough, because you can have more than one pointer in an object
> to fix up.
I was thinking about times where the system would decide to reallocate
something without me asking. Now that I read this again, you are
specifically talking only about times where the user does something that
could reallocate. As such I take back my objection.
Please avoid adding new situations where I have to beware of objects
changing. Iterator invalidation is already something that trips up good
programmers from time to time. Don't make this worse.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1533938708.921335.1470390144.44084910%40webmail.messagingengine.com.
--_----------=_15339387089213350
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="UTF-8"
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type=3D"text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style>
</head>
<body><div style=3D"font-family:Arial;"><br></div>
<div><br></div>
<div><br></div>
<div>On Fri, Aug 10, 2018, at 4:25 PM, Nicol Bolas wrote:<br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial;=
">On Friday, August 10, 2018 at 4:39:48 PM UTC-4, Henry Miller wrote:<br></=
div>
<blockquote defang_data-gmailquote=3D"yes" style=3D"margin-top:0px;margin-r=
ight:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204, 204, 204);padding-left:1ex;"><di=
v><div>On Fri, Aug 10, 2018, at 11:41 AM, <a>floria...@gmail.com</a> wrote:=
<br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial;=
">I was playing with memory allocations, what it is possible to do and how =
it is implemented.<br></div>
<div style=3D"font-family:Arial;">It made me think about relocations, so he=
re is the result of my reflection.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">"Relocation" definition:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">An objec=
t is relocated when its address changes.<br></div>
<div style=3D"font-family:Arial;">This does not necessarily implies a copy =
of its bytes.<br></div>
</div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">When it can occur:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">This cou=
ld happen if a call to realloc is performed.<br></div>
<div style=3D"font-family:Arial;">This could also happen as a compiler opti=
mization<br></div>
</div>
</div>
</blockquote><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">What about memory compaction? This would =
be the most interesting and useful case to me. Memory fragmentation is an u=
nfortunate reality that I sometimes fight. <br></div>
<div style=3D"font-family:Arial;"><br></div>
<blockquote type=3D"cite"><div dir=3D"ltr"><div style=3D"font-family:Arial;=
"><br></div>
<div style=3D"font-family:Arial;"><span class=3D"size" style=3D"font-size:l=
arge">How it can be integrated to the language:</span><br></div>
<div style=3D"margin-left:40px;"><div style=3D"font-family:Arial;">Relocati=
on cannot be a constructor: no new object is created.<br></div>
<div style=3D"font-family:Arial;">Relocation cannot be an assignment operat=
or: Only one object is involved.<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">So here is what I propose:<br></div>
<div style=3D"font-family:Arial;">Every type has a relocation operator that=
takes a pointer and returning <span class=3D"font" style=3D"font-family:&q=
uot;courier new", monospace">void</span> (let's call it <span class=3D=
"font" style=3D"font-family:"courier new", monospace">operator re=
locate</span> to ease the explanation, but I have no strong opinion on the =
syntax).<br></div>
<div style=3D"font-family:Arial;">This operator is called just after the ob=
ject address has changed (for whatever reason), and the pointer argument re=
presents the old address of the object (which is now an invalid address).<b=
r></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">This operator can be deleted or defaulted=
..<br></div>
<div style=3D"font-family:Arial;">The <span class=3D"font" style=3D"font-fa=
mily:"courier new", monospace">operator relocate</span> is trivia=
l iif:<br></div>
</div>
<ul style=3D"margin-left:40px;"><li>it is not user-provided (that is, it is=
implicitly-defined or defaulted)<span><span></span></span><br></li><li><co=
de>T</code> has no virtual member functions<br></li><li><code>T</code> has =
no virtual base classes<br></li><li>the <span class=3D"font" style=3D"font-=
family:"courier new", monospace">operator relocate</span> selecte=
d for every direct base of <code>T</code> is trivial<br></li><li>the <span =
class=3D"font" style=3D"font-family:"courier new", monospace">ope=
rator relocate</span> selected for every non-static class type (or array of=
class type) member of <code>T</code> is trivial<br></li></ul><p style=3D"m=
argin-left:40px;">A trivial <span class=3D"font" style=3D"font-family:"=
;courier new", monospace">operator relocate</span> is basically a noop=
..<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left:40p=
x;">No syntax is proposed to call relocation (apart from <span class=3D"fon=
t" style=3D"font-family:"courier new", monospace">object.operator=
relocate(p)</span>).<br></p><p style=3D"margin-left:40px;"><br></p><p styl=
e=3D"margin-left:40px;">An <span class=3D"font" style=3D"font-family:"=
courier new", monospace">operator relocate</span> shall not change the=
state of the object if the new address is the same as the old address, eve=
n if the operator is not trivial.<br></p><p style=3D"margin-left:40px;">It =
also cannot be virtual (you shall relocate only object through their true t=
ype).<br></p><p style=3D"margin-left:40px;"><br></p><p style=3D"margin-left=
:40px;">I propose that throwing relocation is allowed, but discouraged (but=
if this is problematic, I see no strong reason to keep throwing relocation=
).<br></p><p><br></p><p><span class=3D"size" style=3D"font-size:large">Smal=
l example:</span><br></p><p style=3D"margin-left:40px;"><br></p><div style=
=3D"background-color:rgb(250, 250, 250);border-top-color:rgb(187, 187, 187)=
;border-right-color:rgb(187, 187, 187);border-bottom-color:rgb(187, 187, 18=
7);border-left-color:rgb(187, 187, 187);border-top-style:solid;border-right=
-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-w=
idth:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1=
px;"><div style=3D"font-family:Arial;"><code></code><br></div>
<div><code><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">struct</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colou=
r" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D=
"color:rgb(0, 0, 0)"><br></span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 136)">struct</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
> </span><span class=3D"colour" style=3D"color:rgb(102, 0, 102)">Foo</span>=
<span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"=
colour" style=3D"color:rgb(102, 102, 0)">{</span><span class=3D"colour" sty=
le=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D=
"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rg=
b(102, 102, 0)">*</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
> bar</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span=
><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></span><span class=
=3D"colour" style=3D"color:rgb(102, 102, 0)">};</span><span class=3D"colour=
" style=3D"color:rgb(0, 0, 0)"><br><br></span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 136)">struct</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 0, 1=
02)">Bar</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">{</span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"c=
olour" style=3D"color:rgb(102, 0, 102)">Foo</span><span class=3D"colour" st=
yle=3D"color:rgb(102, 102, 0)">*</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> // foo=
..bar is always equals to this<br><br> </span><span class=3D"colour" s=
tyle=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"c=
olor:rgb(102, 102, 0)">()</span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">:<=
/span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> foo</span><span =
class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</span><span class=3D"co=
lour" style=3D"color:rgb(0, 0, 136)">new</span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(1=
02, 0, 102)">Foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">this</spa=
n><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">})</span><span cl=
ass=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" =
style=3D"color:rgb(102, 102, 0)">{}</span><span class=3D"colour" style=3D"c=
olor:rgb(0, 0, 0)"><code><span class=3D"colour" style=3D"color:rgb(0, 0, 0)=
"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)"=
>~</span><span class=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">()</span><span clas=
s=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" st=
yle=3D"color:rgb(102, 102, 0)">{</span><span class=3D"colour" style=3D"colo=
r:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D"co=
lor:rgb(0, 0, 136)">delete</span><span class=3D"colour" style=3D"color:rgb(=
0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)=
">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> </=
span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">}</span><span =
class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></span></code><br> =
// copy is deleted<br> </span><span class=3D"colour" style=3D"color:r=
gb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">(</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">const=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span cl=
ass=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"co=
lour" style=3D"color:rgb(102, 102, 0)">&)</span><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">delete</=
span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span =
class=3D"colour" style=3D"color:rgb(0, 0, 0)"><code><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=
=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color=
:rgb(102, 102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0,=
0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">opera=
tor</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D(</spa=
n><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">const</span><span c=
lass=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour"=
style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D=
"color:rgb(102, 102, 0)">&)</span><span class=3D"colour" style=3D"color=
:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><=
span class=3D"colour" style=3D"color:rgb(0, 0, 136)">delete</span><span cla=
ss=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colou=
r" style=3D"color:rgb(0, 0, 0)"><br><br> // move needs to set the foo=
..bar to this object<br></span></code> </span><span class=3D"colour" s=
tyle=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"c=
olor:rgb(102, 102, 0)">(</span><span class=3D"colour" style=3D"color:rgb(10=
2, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0=
)">&&</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> ot=
her</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">)</span><=
span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"c=
olour" style=3D"color:rgb(102, 102, 0)">:</span><span class=3D"colour" styl=
e=3D"color:rgb(0, 0, 0)"> foo</span><span class=3D"colour" style=3D"color:r=
gb(102, 102, 0)">(</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)=
">other</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">foo</span><span clas=
s=3D"colour" style=3D"color:rgb(102, 102, 0)">)</span><span class=3D"colour=
" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"colo=
r:rgb(102, 102, 0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"><br> other</span><span class=3D"colour" style=3D"color:rg=
b(102, 102, 0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"=
>foo </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</sp=
an><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 136)">nullptr</span><span class=3D"col=
our" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 0)"><br> foo</span><span class=3D"colour" =
style=3D"color:rgb(102, 102, 0)">.</span><span class=3D"colour" style=3D"co=
lor:rgb(0, 0, 0)">bar </span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">=3D</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </=
span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">this</span><span=
class=3D"colour" style=3D"color:rgb(102, 102, 0)">;</span><span class=3D"c=
olour" style=3D"color:rgb(0, 0, 0)"><br> </span><span class=3D"colour=
" style=3D"color:rgb(102, 102, 0)">}</span><span class=3D"colour" style=3D"=
color:rgb(0, 0, 0)"><br> </span><span class=3D"colour" style=3D"color=
:rgb(102, 0, 102)">Bar</span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> =
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">operator</span=
><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D(</span><span c=
lass=3D"colour" style=3D"color:rgb(102, 0, 102)">Bar</span><span class=3D"c=
olour" style=3D"color:rgb(102, 102, 0)">&&</span><span class=3D"col=
our" style=3D"color:rgb(0, 0, 0)"> other</span><span class=3D"colour" style=
=3D"color:rgb(102, 102, 0)">)</span><span class=3D"colour" style=3D"color:r=
gb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)=
">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> &n=
bsp; swap</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</=
span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">foo</span><span cl=
ass=3D"colour" style=3D"color:rgb(102, 102, 0)">,</span><span class=3D"colo=
ur" style=3D"color:rgb(0, 0, 0)"> other</span><span class=3D"colour" style=
=3D"color:rgb(102, 102, 0)">.</span><span class=3D"colour" style=3D"color:r=
gb(0, 0, 0)">foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">);</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> =
foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span><span=
class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span class=3D=
"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=
=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0=
)"><br> other</span><span class=3D"colour" style=3D"color:rgb(=
102, 102, 0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">f=
oo</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">.</span><s=
pan class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span><span class=3D=
"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span class=3D"colour" =
style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:=
rgb(102, 102, 0)">&</span><span class=3D"colour" style=3D"color:rgb(0, =
0, 0)">other</span><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=
;</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br> &nbs=
p; </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">return</spa=
n><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=
=3D"colour" style=3D"color:rgb(102, 102, 0)">*</span><span class=3D"colour"=
style=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"=
color:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0=
, 0, 0)"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 1=
02, 0)">}</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br><br=
> // If address has changed, reset the foo.bar to point to the new lo=
cation of the object<br> </span><span class=3D"colour" style=3D"color=
:rgb(0, 0, 136)">void</span><span class=3D"colour" style=3D"color:rgb(0, 0,=
0)"> </span><span class=3D"colour" style=3D"color:rgb(0, 0, 136)">operator=
</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"> relocate</span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">(</span><span class=
=3D"colour" style=3D"color:rgb(0, 0, 136)">void</span><span class=3D"colour=
" style=3D"color:rgb(102, 102, 0)">*)</span><span class=3D"colour" style=3D=
"color:rgb(0, 0, 0)"> </span><span class=3D"colour" style=3D"color:rgb(102,=
102, 0)">{</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br>&=
nbsp; foo</span><span class=3D"colour" style=3D"color:rgb(102, 102, =
0)">.</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)">bar </span>=
<span class=3D"colour" style=3D"color:rgb(102, 102, 0)">=3D</span><span cla=
ss=3D"colour" style=3D"color:rgb(0, 0, 0)"> </span><span class=3D"colour" s=
tyle=3D"color:rgb(0, 0, 136)">this</span><span class=3D"colour" style=3D"co=
lor:rgb(102, 102, 0)">;</span><span class=3D"colour" style=3D"color:rgb(0, =
0, 0)"><br> </span><span class=3D"colour" style=3D"color:rgb(102, 102=
, 0)">}</span><span class=3D"colour" style=3D"color:rgb(0, 0, 0)"><br></spa=
n><span class=3D"colour" style=3D"color:rgb(102, 102, 0)">};</span><span cl=
ass=3D"colour" style=3D"color:rgb(0, 0, 0)"></span></code></div>
<div style=3D"font-family:Arial;"><code></code><br></div>
</div>
<p><br></p></div>
</blockquote><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">Your example code is undefined behavior. =
If some other thread access bar::foo after the reallocation and before bar:=
:relocate gets to the fix up line your program goes boom.<br></div>
</div>
</blockquote><div><br></div>
<div>How would that be different from any other data race? Presumably, relo=
cating an object is accessing it. So if two threads are accessing the same =
object at the same time, it's a data race: UB.<br></div>
<div><br></div>
<div>If you need to thread relocation with other accesses, it should be on =
you to provide it. Even atomic pointer fixup operation wouldn't be enough, =
because you can have more than one pointer in an object to fix up.<br></div=
>
</div>
</blockquote><div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">I was thinking about times where the syst=
em would decide to reallocate something without me asking. Now that I read =
this again, you are specifically talking only about times where the user do=
es something that could reallocate. As such I take back my objection. =
<br></div>
<div style=3D"font-family:Arial;"><br></div>
<div style=3D"font-family:Arial;">Please avoid adding new situations where =
I have to beware of objects changing. Iterator invalidation is already some=
thing that trips up good programmers from time to time. Don't make this wor=
se. </div>
</body>
</html>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/1533938708.921335.1470390144.44084910=
%40webmail.messagingengine.com?utm_medium=3Demail&utm_source=3Dfooter">http=
s://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1533938708.921335.=
1470390144.44084910%40webmail.messagingengine.com</a>.<br />
--_----------=_15339387089213350--
.
Author: florian.csdt@gmail.com
Date: Fri, 10 Aug 2018 15:26:45 -0700 (PDT)
Raw View
------=_Part_942_668014882.1533940005741
Content-Type: multipart/alternative;
boundary="----=_Part_943_1287115274.1533940005741"
------=_Part_943_1287115274.1533940005741
Content-Type: text/plain; charset="UTF-8"
> Please avoid adding new situations where I have to beware of objects
> changing. Iterator invalidation is already something that trips up good
> programmers from time to time. Don't make this worse.
>
I dont expect this to be any different than moves.
Moreover, if a std::vector relocates its content, iterators are invalidated
in the same way than without standard re allocations.
All in all, I don't see how it is worse with relocation.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8a4fae1e-8eb5-44fe-8b0c-2a7f7c8c872b%40isocpp.org.
------=_Part_943_1287115274.1533940005741
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div><div=
style=3D"font-family:Arial">Please avoid adding new situations where I hav=
e to beware of objects changing. Iterator invalidation is already something=
that trips up good programmers from time to time. Don't make this wors=
e.=C2=A0</div></div></blockquote><div><br></div><div>I dont expect this to =
be any different than moves.</div><div>Moreover, if a std::vector relocates=
its content, iterators are invalidated in the same way than without standa=
rd re allocations.</div><div>All in all, I don't see how it is worse wi=
th relocation.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/8a4fae1e-8eb5-44fe-8b0c-2a7f7c8c872b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8a4fae1e-8eb5-44fe-8b0c-2a7f7c8c872b=
%40isocpp.org</a>.<br />
------=_Part_943_1287115274.1533940005741--
------=_Part_942_668014882.1533940005741--
.
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 10 Aug 2018 16:53:41 -0700 (PDT)
Raw View
------=_Part_1043_1181101632.1533945221521
Content-Type: multipart/alternative;
boundary="----=_Part_1044_2023029443.1533945221521"
------=_Part_1044_2023029443.1533945221521
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Friday, August 10, 2018 at 10:19:01 AM UTC-7, floria...@gmail.com wrote:
>
> No, I was not aware of this very proposal. (That's quite hard to keep=20
> track of all proposals)
>
> However, it also shares some issues with most other proposals.
> Namely: it talks about destructive move (two different storages, moving=
=20
> the actual object from one to the other).
> Also, only trivial destructive moves are considered (no user defined).
>
Please elaborate on this last point above ("no user-defined") =E2=80=94 eit=
her=20
here, or in private email if you feel more like it. (I'm the author of=20
P1144 and definitely want to hear if it doesn't solve your use-case!)
=20
> But my proposal talks about in-place relocation: there is one single=20
> storage whose address has changed.
> And the relocation can be user-defined (a std::list could be made nothrow=
=20
> relocatable).
>
By P1144's definition, std::is_nothrow_relocatable_v<std::list<T>> and not=
=20
std::is_trivially_relocatable_v<std::list<T>> <https://godbolt.org/g/yWBAfK=
>.=20
I think this agrees with your definitions as well, right?
I believe I understand the intuition behind your proposal. Where P1144=20
defines "relocate(src,dst) =3D move(src,dst) + destroy(src)", you prefer to=
=20
define "relocate(src,dst) =3D memcpy(src,dst) + fixup(src,dst)". Your=20
`operator relocate` corresponds to the "fixup(src,dst)" step: it is called=
=20
on the destination object after the memcpy has happened, and its job is to=
=20
repair the damage caused by the memcpy.
In the absolute worst case, "fixup(src,dst)" can be implemented as=20
"move(src,dst) + destroy(src)". In the average case, it can be implemented=
=20
as "fixup-after-move(dst) + destroy(src)". In the case corresponding to=20
"trivially relocatable", by definition, it can be implemented as a no-op,=
=20
because a trivially relocatable type by definition can be relocated as-if=
=20
by memcpy and therefore requires no extra fixup step *after* the memcpy.
I agree with other commenters (e.g. Nicol) that your approach is much more=
=20
damaging to the object model than P1144's. (And I have been told by several=
=20
people, I think again including Nicol, that even P1144 is already too=20
damaging! My hope is that we will get std::bless<T>() to magically fix all=
=20
our problems; and in the meantime, P1144 is demonstrably implementable and=
=20
usable=20
<https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocat=
able/>=20
even if it is technically problematic.)
IIUC, you believe that one advantage of your proposal is that it can be=20
used even in situations where no physical `memcpy` happens, e.g. when we=20
play tricks with mmap and/or page tables to "wormhole" a range of bytes=20
from address A to address B without a physical `memcpy`. I believe that=20
P1144 applies equally well to these situations =E2=80=94 perhaps better! I=
n either=20
your scheme or mine, for trivially relocatable types, we just=20
memcpy-or-wormhole the bytes from A to B and we're done. Where we differ is=
=20
for non-trivially relocatable types. In P1144's scheme, we just say=20
"Wormholing non-trivially-relocatable types is not supported; you're on=20
your own." In your scheme, you permit the possibility that someone could=
=20
wormhole an object from A to B and then manually call `operator relocate`=
=20
to perform the fixup. But, if we're assuming wormholes exist, then I don't=
=20
understand why you'd assume that the "source address" of the=20
`fixup(src,dst)` is still accessible, or even addressable, by the time the=
=20
wormhole has happened!
An obvious example here is if we're sharing a memory segment between two=20
processes, so that the destination end of the wormhole is in a completely=
=20
different address space from the source end. Neither side of the shared=20
memory segment has enough information to run `fixup(src,dst)`. However,=20
I'll admit that shared-memory-segment is a bad use-case for "trivially=20
relocatable" in general; it really needs a different, larger, more emergent=
=20
notion, which I call "position-independent" and which I recently heard=20
Ronan Keryell call "translation-independent." So I offer=20
shared-memory-segment as an easily understandable example of a wormhole=20
with mutually unaddressible ends, where `fixup(src,dst)` is inexpressible =
=E2=80=94=20
an example of why your scheme *doesn't add any value* for the wormhole case=
=20
compared to P1144. I don't offer it as an example of P1144 solving problems=
=20
related to shared-memory-segment in general (because it doesn't).
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/4fb6a8b4-05a1-424e-88b1-275878e1f66a%40isocpp.or=
g.
------=_Part_1044_2023029443.1533945221521
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, August 10, 2018 at 10:19:01 AM UTC-7, floria...=
@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">No, I was not aware of this very proposal. (That's quite hard to ke=
ep track of all proposals)<br><br>However, it also shares some issues with =
most other proposals.<br>Namely: it talks about destructive move (two diffe=
rent storages, moving the actual object from one to the other).<br>Also, on=
ly trivial destructive moves are considered (no user defined).<br></div></b=
lockquote><div><br></div><div>Please elaborate on this last point above (&q=
uot;no user-defined") =E2=80=94 either here, or in private email if yo=
u feel more like it. (I'm the author of P1144 and definitely want to he=
ar if it doesn't solve your use-case!)</div><div><br></div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">But my p=
roposal talks about in-place relocation: there is one single storage whose =
address has changed.<br>And the relocation can be user-defined (a std::list=
could be made nothrow relocatable).<br></div></blockquote><div><br></div><=
div>By P1144's definition, <a href=3D"https://godbolt.org/g/yWBAfK">std=
::is_nothrow_relocatable_v<std::list<T>> and not std::is_trivia=
lly_relocatable_v<std::list<T>></a>. =C2=A0I think this agrees =
with your definitions as well, right?</div><div><br></div><div>I believe I =
understand the intuition behind your proposal. Where P1144 defines "re=
locate(src,dst) =3D move(src,dst) + destroy(src)", you prefer to defin=
e "relocate(src,dst) =3D memcpy(src,dst) + fixup(src,dst)". =C2=
=A0Your `operator relocate` corresponds to the "fixup(src,dst)" s=
tep: it is called on the destination object after the memcpy has happened, =
and its job is to repair the damage caused by the memcpy.</div><div><br></d=
iv><div>In the absolute worst case, "fixup(src,dst)" can be imple=
mented as "move(src,dst) + destroy(src)". In the average case, it=
can be implemented as "fixup-after-move(dst) + destroy(src)". In=
the case corresponding to "trivially relocatable", by definition=
, it can be implemented as a no-op, because a trivially relocatable type by=
definition can be relocated as-if by memcpy and therefore requires no extr=
a fixup step <i>after</i> the memcpy.</div><div><br></div><div>I agree with=
other commenters (e.g. Nicol) that your approach is much more damaging to =
the object model than P1144's. (And I have been told by several people,=
I think again including Nicol, that even P1144 is already too damaging! =
=C2=A0My hope is that we will get std::bless<T>() to magically fix al=
l our problems; and in the meantime, P1144 is <a href=3D"https://quuxpluson=
e.github.io/blog/2018/07/18/announcing-trivially-relocatable/">demonstrably=
implementable and usable</a> even if it is technically problematic.)</div>=
<div><br></div><div>IIUC, you believe that one advantage of your proposal i=
s that it can be used even in situations where no physical `memcpy` happens=
, e.g. when we play tricks with mmap and/or page tables to "wormhole&q=
uot; a range of bytes from address A to address B without a physical `memcp=
y`. =C2=A0I believe that P1144 applies equally well to these situations =E2=
=80=94 perhaps better! =C2=A0In either your scheme or mine, for trivially r=
elocatable types, we just memcpy-or-wormhole the bytes from A to B and we&#=
39;re done. Where we differ is for non-trivially relocatable types. In P114=
4's scheme, we just say "Wormholing non-trivially-relocatable type=
s is not supported; you're on your own." =C2=A0In your scheme, you=
permit the possibility that someone could wormhole an object from A to B a=
nd then manually call `operator relocate` to perform the fixup. But, if we&=
#39;re assuming wormholes exist, then I don't understand why you'd =
assume that the "source address" of the `fixup(src,dst)` is still=
accessible, or even addressable, by the time the wormhole has happened!</d=
iv><div><br></div><div>An obvious example here is if we're sharing a me=
mory segment between two processes, so that the destination end of the worm=
hole is in a completely different address space from the source end. Neithe=
r side of the shared memory segment has enough information to run `fixup(sr=
c,dst)`. However, I'll admit that shared-memory-segment is a bad use-ca=
se for "trivially relocatable" in general; it really needs a diff=
erent, larger, more emergent notion, which I call "position-independen=
t" and which I recently heard Ronan Keryell call "translation-ind=
ependent." =C2=A0So I offer shared-memory-segment as an easily underst=
andable example of a wormhole with mutually unaddressible ends, where `fixu=
p(src,dst)` is inexpressible =E2=80=94 an example of why your scheme <i>doe=
sn't add any value</i> for the wormhole case compared to P1144. I don&#=
39;t offer it as an example of P1144 solving=C2=A0problems related to share=
d-memory-segment in general (because it doesn't).</div><div><br></div><=
div>=E2=80=93Arthur</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4fb6a8b4-05a1-424e-88b1-275878e1f66a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4fb6a8b4-05a1-424e-88b1-275878e1f66a=
%40isocpp.org</a>.<br />
------=_Part_1044_2023029443.1533945221521--
------=_Part_1043_1181101632.1533945221521--
.
Author: florian.csdt@gmail.com
Date: Sat, 11 Aug 2018 01:51:03 -0700 (PDT)
Raw View
------=_Part_940_1286523968.1533977464053
Content-Type: multipart/alternative;
boundary="----=_Part_941_1381808574.1533977464053"
------=_Part_941_1381808574.1533977464053
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le samedi 11 ao=C3=BBt 2018 01:53:41 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Friday, August 10, 2018 at 10:19:01 AM UTC-7, floria...@gmail.com=20
> wrote:
>>
>> No, I was not aware of this very proposal. (That's quite hard to keep=20
>> track of all proposals)
>>
>> However, it also shares some issues with most other proposals.
>> Namely: it talks about destructive move (two different storages, moving=
=20
>> the actual object from one to the other).
>> Also, only trivial destructive moves are considered (no user defined).
>>
>
> Please elaborate on this last point above ("no user-defined") =E2=80=94 e=
ither=20
> here, or in private email if you feel more like it. (I'm the author of=20
> P1144 and definitely want to hear if it doesn't solve your use-case!)
>
With your proposal, the user cannot write its own relocation code.
I'll explain it further to answer your other comments directly.
=20
>
> =20
>
>> But my proposal talks about in-place relocation: there is one single=20
>> storage whose address has changed.
>> And the relocation can be user-defined (a std::list could be made nothro=
w=20
>> relocatable).
>>
>
> By P1144's definition, std::is_nothrow_relocatable_v<std::list<T>> and=20
> not std::is_trivially_relocatable_v<std::list<T>>=20
> <https://godbolt.org/g/yWBAfK>. I think this agrees with your=20
> definitions as well, right?
>
Where we agree is about what types would be trivially relocatable (our=20
definitions are compatible here).
However, as we don't share the same definition for relocation, not the same=
=20
types will be nothrow relocatable.
For you, if a type is movable and destructible, it is relocatable. For me,=
=20
if there is non-deleted operators delocate/relocate, the type is=20
relocatable.
So with my design, it is possible to have non-movable non copyable types=20
that are relocatable (that is probably not a sane default), and it is also=
=20
possible to have copyable movable types that are not relocatable.
I want to highlight that some part of your proposal is forward compatible=
=20
with mine.
Namely: which types are trivially relocatible, the fact that types=20
following the rule of 0 would get trivial relocability if all its=20
members/bases are trivially relocatable, and what is possible to do with=20
trivially relocatable types.
Your proposed attribute would also be forward compatible, but redondant.
However, the notion of nothrow relocatable is different and are mostly not=
=20
compatible.
So if you want to make your proposal compatible with mine, I would propose=
=20
you to say: only trivially relocatable types are relocatable. But the=20
decision is up to you.
=20
>
> I believe I understand the intuition behind your proposal. Where P1144=20
> defines "relocate(src,dst) =3D move(src,dst) + destroy(src)", you prefer =
to=20
> define "relocate(src,dst) =3D memcpy(src,dst) + fixup(src,dst)". Your=20
> `operator relocate` corresponds to the "fixup(src,dst)" step: it is calle=
d=20
> on the destination object after the memcpy has happened, and its job is t=
o=20
> repair the damage caused by the memcpy.
>
>
After all the other comments, I changed my opinion about what should be the=
=20
relocation.
Now relocation is done in 2 explicit steps: delocate() and relocate().
Delocate() could be seen as: prepare fixup
Relocate() could be seen as: do fixup
So "relocate(src, dst)" would be implemented: src.delocate() + memcpy(dst,=
=20
src) + dst.relocate().
But yes, my approach is to fix the object after memcpy. (the memcpy might=
=20
not happen at all).
=20
> In the absolute worst case, "fixup(src,dst)" can be implemented as=20
> "move(src,dst) + destroy(src)". In the average case, it can be implemente=
d=20
> as "fixup-after-move(dst) + destroy(src)". In the case corresponding to=
=20
> "trivially relocatable", by definition, it can be implemented as a no-op,=
=20
> because a trivially relocatable type by definition can be relocated as-if=
=20
> by memcpy and therefore requires no extra fixup step *after* the memcpy.
>
>
I have no "fixup(src, dst)". This is not valid view of what I mean by=20
relocation: only one storage exist. This storage can be moved (change=20
address), but the old position of the storage might not be available at the=
=20
time of the fixup.
And the is no fixup-after-move because there is no move (no move=20
constructor/assignment is called).
Yes, with my view, trivial relocation is a noop.
=20
> I agree with other commenters (e.g. Nicol) that your approach is much mor=
e=20
> damaging to the object model than P1144's. (And I have been told by sever=
al=20
> people, I think again including Nicol, that even P1144 is already too=20
> damaging! My hope is that we will get std::bless<T>() to magically fix a=
ll=20
> our problems; and in the meantime, P1144 is demonstrably implementable=20
> and usable=20
> <https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-reloc=
atable/>=20
> even if it is technically problematic.)
>
I wouldn't my approach is more damaging to the object model. I would say=20
more intrusive. Sometimes, small fixes are harder to accept because they=20
are patchwork to make something work (I don't say that's your case). Those=
=20
times, bigger changes might have more chance to be adopted because they=20
integrate more nicely. So I don't see why making big changes that wouldn't=
=20
break code couldn't make it. Of course, it will require more effort to be=
=20
accepted, but looking at the big picture, that would be definitely worth it=
..
Relocation would be an enabling feature.
Concerning std::bless<T>(), I didn't anticipated it, but my proposal ends=
=20
up closer and closer to this.
So my opinion on this: I would prefer something defined within the class=20
because it needs the possibility to be defaulted.
Moreover, as far as I understand, Nial's proposal doesn't say anything=20
about user defined std::bless<T>.
That being said, I would say my proposal and Nial's one are orthogonal,=20
they can be adopted in whatever order. My relocation would then be the=20
internal mechanism used by std::bless<T> that could be standardized as such=
=20
afterwards. And my proposal doesn't need Nial's one as they are many other=
=20
use cases.
=20
>
> IIUC, you believe that one advantage of your proposal is that it can be=
=20
> used even in situations where no physical `memcpy` happens, e.g. when we=
=20
> play tricks with mmap and/or page tables to "wormhole" a range of bytes=
=20
> from address A to address B without a physical `memcpy`. I believe that=
=20
> P1144 applies equally well to these situations =E2=80=94 perhaps better! =
In either=20
> your scheme or mine, for trivially relocatable types, we just=20
> memcpy-or-wormhole the bytes from A to B and we're done. Where we differ =
is=20
> for non-trivially relocatable types. In P1144's scheme, we just say=20
> "Wormholing non-trivially-relocatable types is not supported; you're on=
=20
> your own." In your scheme, you permit the possibility that someone could=
=20
> wormhole an object from A to B and then manually call `operator relocate`=
=20
> to perform the fixup. But, if we're assuming wormholes exist, then I don'=
t=20
> understand why you'd assume that the "source address" of the=20
> `fixup(src,dst)` is still accessible, or even addressable, by the time th=
e=20
> wormhole has happened!
>
>
Getting the source address was a defect of the single step apporach (it was=
=20
required only if the fixup needed to know by how much it was displaced,=20
basically).
But is not required anymore with the two steps approach: delocate() and=20
relocate() don't take any argument (apart from this).
So it now support any crazy byte moving operation. And wormholing is not an=
=20
issue.
=20
> An obvious example here is if we're sharing a memory segment between two=
=20
> processes, so that the destination end of the wormhole is in a completely=
=20
> different address space from the source end. Neither side of the shared=
=20
> memory segment has enough information to run `fixup(src,dst)`. However,=
=20
> I'll admit that shared-memory-segment is a bad use-case for "trivially=20
> relocatable" in general; it really needs a different, larger, more emerge=
nt=20
> notion, which I call "position-independent" and which I recently heard=20
> Ronan Keryell call "translation-independent." So I offer=20
> shared-memory-segment as an easily understandable example of a wormhole=
=20
> with mutually unaddressible ends, where `fixup(src,dst)` is inexpressible=
=E2=80=94=20
> an example of why your scheme *doesn't add any value* for the wormhole=20
> case compared to P1144. I don't offer it as an example of P1144=20
> solving problems related to shared-memory-segment in general (because it=
=20
> doesn't).
>
>
First, as I explained just above, I changed my design to now require 2=20
steps: delocate()/relocate(). Delocate doesn't know what will be the new=20
address, and relocate doesn't know what was the old address. So if an=20
object needs to know (for whatever reason) by how much it was displaced, it=
=20
should store the information required during the delocate step and use it=
=20
in the relocate step.
These 2 steps makes it possible to tackle the address-space change=20
(communication between processes for instance).
However, I don't plan to standardize this part (I let this part to Nial).=
=20
For now, I will just say that it is undefined behaviour to delocate an=20
object without relocating it within the program itself, the same with=20
relocating an object that was not delocated in the program.
We can make it defined behaviour afterwards.
Concerning your notion of position-independent, I have the feeling that=20
this notion would match trivial relocatibility in most cases (all?).
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/b7370533-65ce-4be2-ba22-9a8546df9c2e%40isocpp.or=
g.
------=_Part_941_1381808574.1533977464053
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le samedi 11 ao=C3=BBt 2018 01:53:41 UTC+2, Arthur=
O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr">On Friday, August 10, 2018 at 10:19:01 AM UTC-7, <a>flor=
ia...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr">No, I was not aware of this very proposal. (That's quite hard =
to keep track of all proposals)<br><br>However, it also shares some issues =
with most other proposals.<br>Namely: it talks about destructive move (two =
different storages, moving the actual object from one to the other).<br>Als=
o, only trivial destructive moves are considered (no user defined).<br></di=
v></blockquote><div><br></div><div>Please elaborate on this last point abov=
e ("no user-defined") =E2=80=94 either here, or in private email =
if you feel more like it. (I'm the author of P1144 and definitely want =
to hear if it doesn't solve your use-case!)</div></div></blockquote><di=
v><br></div><div>With your proposal, the user cannot write its own relocati=
on code.</div><div>I'll explain it further to answer your other comment=
s directly.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">But my proposal talks about in-plac=
e relocation: there is one single storage whose address has changed.<br>And=
the relocation can be user-defined (a std::list could be made nothrow relo=
catable).<br></div></blockquote><div><br></div><div>By P1144's definiti=
on, <a href=3D"https://godbolt.org/g/yWBAfK" target=3D"_blank" rel=3D"nofol=
low" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%=
3A%2F%2Fgodbolt.org%2Fg%2FyWBAfK\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEv=
jt6nMc8h1SnuS5LCPd8SYuXdrQ';return true;" onclick=3D"this.href=3D'h=
ttps://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FyWBAfK\x26sa=
\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEvjt6nMc8h1SnuS5LCPd8SYuXdrQ';return=
true;">std::is_nothrow_relocatable_v<<wbr>std::list<T>> and no=
t std::is_trivially_relocatable_<wbr>v<std::list<T>></a>. =C2=
=A0I think this agrees with your definitions as well, right?</div></div></b=
lockquote><div><br></div><div>Where we agree is about what types would be t=
rivially relocatable (our definitions are compatible here).</div><div>Howev=
er, as we don't share the same definition for relocation, not the same =
types will be nothrow relocatable.</div><div><br></div><div>For you, if a t=
ype is movable and destructible, it is relocatable. For me, if there is non=
-deleted operators delocate/relocate, the type is relocatable.</div><div>So=
with my design, it is possible to have non-movable non copyable types that=
are relocatable (that is probably not a sane default), and it is also poss=
ible to have copyable movable types that are not relocatable.</div><div><br=
></div><div>I want to highlight that some part of your proposal is forward =
compatible with mine.</div><div>Namely: which types are trivially relocatib=
le, the fact that types following the rule of 0 would get trivial relocabil=
ity if all its members/bases are trivially relocatable, and what is possibl=
e to do with trivially relocatable types.</div><div>Your proposed attribute=
would also be forward compatible, but redondant.</div><div><br></div><div>=
However, the notion of nothrow relocatable is different and are mostly not =
compatible.</div><div>So if you want to make your proposal compatible with =
mine, I would propose you to say: only trivially relocatable types are relo=
catable. But the decision is up to you.<br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>I =
believe I understand the intuition behind your proposal. Where P1144 define=
s "relocate(src,dst) =3D move(src,dst) + destroy(src)", you prefe=
r to define "relocate(src,dst) =3D memcpy(src,dst) + fixup(src,dst)&qu=
ot;. =C2=A0Your `operator relocate` corresponds to the "fixup(src,dst)=
" step: it is called on the destination object after the memcpy has ha=
ppened, and its job is to repair the damage caused by the memcpy.</div><div=
><br></div></div></blockquote><div><br></div><div>After all the other comme=
nts, I changed my opinion about what should be the relocation.</div><div>No=
w relocation is done in 2 explicit steps: delocate() and relocate().</div><=
div>Delocate() could be seen as: prepare fixup<br></div><div>Relocate() cou=
ld be seen as: do fixup</div><div><br></div><div>So "relocate(src, dst=
)" would be implemented: src.delocate() + memcpy(dst, src) + dst.reloc=
ate().</div><div><br></div><div>But yes, my approach is to fix the object a=
fter memcpy. (the memcpy might not happen at all).<br></div><div><br></div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div></div><div>In the absolute worst case, "fixup(src,dst)" =
can be implemented as "move(src,dst) + destroy(src)". In the aver=
age case, it can be implemented as "fixup-after-move(dst) + destroy(sr=
c)". In the case corresponding to "trivially relocatable", b=
y definition, it can be implemented as a no-op, because a trivially relocat=
able type by definition can be relocated as-if by memcpy and therefore requ=
ires no extra fixup step <i>after</i> the memcpy.</div><div><br></div></div=
></blockquote><div><br></div><div>I have no "fixup(src, dst)". Th=
is is not valid view of what I mean by relocation: only one storage exist. =
This storage can be moved (change address), but the old position of the sto=
rage might not be available at the time of the fixup.</div><div>And the is =
no fixup-after-move because there is no move (no move constructor/assignmen=
t is called).</div><div><br></div><div>Yes, with my view, trivial relocatio=
n is a noop.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div></div><div>I agree with other commenters (e.=
g. Nicol) that your approach is much more damaging to the object model than=
P1144's. (And I have been told by several people, I think again includ=
ing Nicol, that even P1144 is already too damaging! =C2=A0My hope is that w=
e will get std::bless<T>() to magically fix all our problems; and in =
the meantime, P1144 is <a href=3D"https://quuxplusone.github.io/blog/2018/0=
7/18/announcing-trivially-relocatable/" target=3D"_blank" rel=3D"nofollow" =
onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F=
%2Fquuxplusone.github.io%2Fblog%2F2018%2F07%2F18%2Fannouncing-trivially-rel=
ocatable%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGEA9QMgWs5WBFLICjqL2WLB=
LKLIg';return true;" onclick=3D"this.href=3D'https://www.google.com=
/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.io%2Fblog%2F2018%2F07%2F18%2Fann=
ouncing-trivially-relocatable%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGE=
A9QMgWs5WBFLICjqL2WLBLKLIg';return true;">demonstrably implementable an=
d usable</a> even if it is technically problematic.)</div></div></blockquot=
e><div><br></div><div>I wouldn't my approach is more damaging to the ob=
ject model. I would say more intrusive. Sometimes, small fixes are harder t=
o accept because they are patchwork to make something work (I don't say=
that's your case). Those times, bigger changes might have more chance =
to be adopted because they integrate more nicely. So I don't see why ma=
king big changes that wouldn't break code couldn't make it. Of cour=
se, it will require more effort to be accepted, but looking at the big pict=
ure, that would be definitely worth it.</div><div>Relocation would be an en=
abling feature.<br></div><div><br></div><div>Concerning std::bless<T>=
(), I didn't anticipated it, but my proposal ends up closer and closer =
to this.</div><div>So my opinion on this: I would prefer something defined =
within the class because it needs the possibility to be defaulted.</div><di=
v>Moreover, as far as I understand, Nial's proposal doesn't say any=
thing about user defined std::bless<T>.</div><div><br></div><div>That=
being said, I would say my proposal and Nial's one are orthogonal, the=
y can be adopted in whatever order. My relocation would then be the interna=
l mechanism used by std::bless<T> that could be standardized as such =
afterwards. And my proposal doesn't need Nial's one as they are man=
y other use cases.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>IIUC, you believe that =
one advantage of your proposal is that it can be used even in situations wh=
ere no physical `memcpy` happens, e.g. when we play tricks with mmap and/or=
page tables to "wormhole" a range of bytes from address A to add=
ress B without a physical `memcpy`. =C2=A0I believe that P1144 applies equa=
lly well to these situations =E2=80=94 perhaps better! =C2=A0In either your=
scheme or mine, for trivially relocatable types, we just memcpy-or-wormhol=
e the bytes from A to B and we're done. Where we differ is for non-triv=
ially relocatable types. In P1144's scheme, we just say "Wormholin=
g non-trivially-relocatable types is not supported; you're on your own.=
" =C2=A0In your scheme, you permit the possibility that someone could =
wormhole an object from A to B and then manually call `operator relocate` t=
o perform the fixup. But, if we're assuming wormholes exist, then I don=
't understand why you'd assume that the "source address" =
of the `fixup(src,dst)` is still accessible, or even addressable, by the ti=
me the wormhole has happened!</div><div><br></div></div></blockquote><div><=
br></div><div>Getting the source address was a defect of the single step ap=
porach (it was required only if the fixup needed to know by how much it was=
displaced, basically).</div><div>But is not required anymore with the two =
steps approach: delocate() and relocate() don't take any argument (apar=
t from this).</div><div>So it now support any crazy byte moving operation. =
And wormholing is not an issue.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>An obvious exa=
mple here is if we're sharing a memory segment between two processes, s=
o that the destination end of the wormhole is in a completely different add=
ress space from the source end. Neither side of the shared memory segment h=
as enough information to run `fixup(src,dst)`. However, I'll admit that=
shared-memory-segment is a bad use-case for "trivially relocatable&qu=
ot; in general; it really needs a different, larger, more emergent notion, =
which I call "position-independent" and which I recently heard Ro=
nan Keryell call "translation-independent." =C2=A0So I offer shar=
ed-memory-segment as an easily understandable example of a wormhole with mu=
tually unaddressible ends, where `fixup(src,dst)` is inexpressible =E2=80=
=94 an example of why your scheme <i>doesn't add any value</i> for the =
wormhole case compared to P1144. I don't offer it as an example of P114=
4 solving=C2=A0problems related to shared-memory-segment in general (becaus=
e it doesn't).</div><div><br></div></div></blockquote><div><br></div><d=
iv>First, as I explained just above, I changed my design to now require 2 s=
teps: delocate()/relocate(). Delocate doesn't know what will be the new=
address, and relocate doesn't know what was the old address. So if an =
object needs to know (for whatever reason) by how much it was displaced, it=
should store the information required during the delocate step and use it =
in the relocate step.</div><div>These 2 steps makes it possible to tackle t=
he address-space change (communication between processes for instance).</di=
v><div><br></div><div>However, I don't plan to standardize this part (I=
let this part to Nial). For now, I will just say that it is undefined beha=
viour to delocate an object without relocating it within the program itself=
, the same with relocating an object that was not delocated in the program.=
</div>We can make it defined behaviour afterwards.<br><br>Concerning your n=
otion of position-independent, I have the feeling that this notion would ma=
tch trivial relocatibility in most cases (all?).<br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/b7370533-65ce-4be2-ba22-9a8546df9c2e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b7370533-65ce-4be2-ba22-9a8546df9c2e=
%40isocpp.org</a>.<br />
------=_Part_941_1381808574.1533977464053--
------=_Part_940_1286523968.1533977464053--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sat, 11 Aug 2018 11:57:22 -0700
Raw View
--0000000000003b80aa05732d6e76
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sat, Aug 11, 2018 at 1:51 AM, <florian.csdt@gmail.com> wrote:
> Le samedi 11 ao=C3=BBt 2018 01:53:41 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>
>> On Friday, August 10, 2018 at 10:19:01 AM UTC-7, floria...@gmail.com
>> wrote:
>>>
>>> No, I was not aware of this very proposal. (That's quite hard to keep
>>> track of all proposals)
>>>
>>> However, it also shares some issues with most other proposals.
>>> Namely: it talks about destructive move (two different storages, moving
>>> the actual object from one to the other).
>>> Also, only trivial destructive moves are considered (no user defined).
>>>
>>
>> Please elaborate on this last point above ("no user-defined") =E2=80=94 =
either
>> here, or in private email if you feel more like it. (I'm the author of
>> P1144 and definitely want to hear if it doesn't solve your use-case!)
>>
>
> With your proposal, the user cannot write its own relocation code.
> I'll explain it further to answer your other comments directly.
>
Ah. If I understand correctly, this is merely an artifact of our different
definitions of "relocate."
For my P1144, "relocate =3D move + destroy," and therefore if you want to
customize how your type is "relocated," you just give it a user-provided
move-constructor and/or a user-provided destructor =E2=80=94 the same thing=
you
already do today.
For your scheme, as originally described, I said it was "relocate =3D memcp=
y
+ fixup." You have now changed it (good!) to what I would call "relocate =
=3D
serialize + memcpy + deserialize." Now here's where we crossed wires. In
your old scheme, I was using the term "relocate" to mean the *entire*
operation, but I now see that you were using the term "relocate" to mean *j=
ust
the fixup half* of the operation. In your new scheme, I assume, you would
use the term "relocate" to mean *just the deserialize part* of the
operation.
So I now agree, under your terminology, P1144 does not permit the user to
define a "relocate" operation, because P1144 does not admit the existence
of any such operation. P1144 doesn't have what I would call a "fixup" or
"deserialize" step. It *only* has move plus destroy. You agree that these
two operations are both customizable by the user; you just disagree that
either of them, or the combination of both of them, should be known by the
word "relocate." I strongly disagree, of course. :)
If you're going to be using the word "relocate" to mean *just the
deserialization step* of your three-step process, could you please provide
a word to refer to the *entire* three-step process as a whole? I (and
Niall AFAIK, and Nicol) have been using the word "relocate" to refer to
this *entire* process =E2=80=94 although of course we all disagree as to ho=
w many
steps the process "really" has, and what the names of those steps are.
> But my proposal talks about in-place relocation: there is one single
>>> storage whose address has changed.
>>> And the relocation can be user-defined (a std::list could be made
>>> nothrow relocatable).
>>>
>>
>> By P1144's definition, std::is_nothrow_relocatable_v<std::list<T>> and
>> not std::is_trivially_relocatable_v<std::list<T>>
>> <https://godbolt.org/g/yWBAfK>. I think this agrees with your
>> definitions as well, right?
>>
>
> Where we agree is about what types would be trivially relocatable (our
> definitions are compatible here).
> However, as we don't share the same definition for relocation, not the
> same types will be nothrow relocatable.
>
Okay, agreed.
Your old scheme defined "entireprocess =3D memcpy + relocate" (where I woul=
d
say "relocate =3D memcpy + fixup"). So for me, "nothrow relocatable" means
"the entire process is nothrow", whereas for you, "nothrow relocatable"
means "just the fixup step is nothrow."
However, in your scheme, if the fixup step is nothrow, then *surely* the
entire process is nothrow! The memcpy better not throw, right?
So we ought to agree about the end result: if the entire process (in your
scheme) is nothrow, then the entire process (in P1144's scheme) is nothrow,
because we both agree on the starting and ending states for the entire
process, regardless of whether we call the entire process "relocation" or
something else.
But this seems largely irrelevant to the discussion, so I'd be okay
dropping this subject if you are.
For you, if a type is movable and destructible, it is relocatable. For me,
> if there is non-deleted operators delocate/relocate, the type is
> relocatable.
> So with my design, it is possible to have non-movable non copyable types
> that are relocatable (that is probably not a sane default),
>
Agreed. See
https://quuxplusone.github.io/blog/2018/07/06/thoughts-on-sanely-move-assig=
nable/#one-particular-kind-of-type-is-o
and it is also possible to have copyable movable types that are not
> relocatable.
>
....because you define "relocatable" to mean not just
"gettable-from-point-A-to-point-B" but "gettable *by this specific
mechanism* involving `operator relocate`." So by your definition, IIUC,
std::string would not be relocatable at all; boost::unique_ptr would not be
relocatable at all; folly::FBVector would not be relocatable at all...
This means that you wouldn't be able to use "relocatable" as a building
block for generic algorithms. Any algorithm that tried to use "operator
relocate" internally would quickly discover that it failed to compile for
just about every class type in the world, except those that had been
specifically designed by a C++2a programmer and provided their own
"operator relocate".
That sounds like a very tough sell.
Contrast that to C++11 move semantics: any copy-constructible C++03 type
magically becomes "move-constructible" in C++11 (because the compiler
happily uses the copy constructor even on an rvalue). Contrast that to
P1144 relocation: any move-constructible, destructible C++11 type magically
becomes "relocatable" in P1144 (because the library happily uses the
move-constructor and destructor when it detects that memcpy would be
inappropriate), and furthermore, many C++11 types magically become
"trivially relocatable" in P1144 (because the compiler detects that they
are).
You seem to be saying that nothing should ever be "efficiently relocatable"
unless the programmer opts in by implementing `operator relocate` (and now
`operator delocate` as well). I don't like that idea. I want to get
"efficiently relocatable" for free. That's why P1144.
> I want to highlight that some part of your proposal is forward compatible
> with mine.
> Namely: which types are trivially relocatible, the fact that types
> following the rule of 0 would get trivial relocability if all its
> members/bases are trivially relocatable, and what is possible to do with
> trivially relocatable types.
> Your proposed attribute would also be forward compatible, but redondant.
>
IIUC, you'd propose the following general idea:
template<class T>
class RedPtr {
T *m_ptr;
public:
RedPtr(RedPtr&&);
~RedPtr();
};
static_assert(not is_florian_relocatable_v<RedPtr<int>>);
static_assert(not is_florian_trivially_relocatable_v<RedPtr<int>>);
template<class T>
class YellowPtr {
T *m_ptr;
public:
YellowPtr(YellowPtr&&);
operator delocate() {}
operator relocate() {}
~YellowPtr();
};
static_assert(is_florian_relocatable_v<YellowPtr<int>>);
static_assert(not is_florian_trivially_relocatable_v<YellowPtr<int>>);
template<class T>
class GreenPtr {
T *m_ptr;
public:
GreenPtr(GreenPtr&&);
operator delocate() =3D default;
operator relocate() =3D default;
~GreenPtr();
};
static_assert(is_florian_relocatable_v<GreenPtr<int>>);
static_assert(is_florian_trivially_relocatable_v<GreenPtr<int>>);
(Notice that these Ptr types are intentionally stripped-down versions of
`boost::unique_ptr<T>`.)
After all the other comments, I changed my opinion about what should be the
> relocation.
> Now relocation is done in 2 explicit steps: delocate() and relocate().
> Delocate() could be seen as: prepare fixup
> Relocate() could be seen as: do fixup
> So "relocate(src, dst)" would be implemented: src.delocate() + memcpy(dst=
,
> src) + dst.relocate().
> But yes, my approach is to fix the object after memcpy. (the memcpy might
> not happen at all).
>
>
>> In the absolute worst case, "fixup(src,dst)" can be implemented as
>> "move(src,dst) + destroy(src)". In the average case, it can be implement=
ed
>> as "fixup-after-move(dst) + destroy(src)". In the case corresponding to
>> "trivially relocatable", by definition, it can be implemented as a no-op=
,
>> because a trivially relocatable type by definition can be relocated as-i=
f
>> by memcpy and therefore requires no extra fixup step *after* the memcpy.
>>
>
> I have no "fixup(src, dst)".
>
Well, you don't *now*, but you did when I wrote my reply. :D
Your old scheme required `operator relocate` to take two parameters: the
implicit `this` pointer (pointing to dst) and a `void*` function parameter
(pointing to src).
Your new scheme doesn't require that src parameter at `operator relocate`
time; you've replaced it with a src parameter at `operator delocate` time.
I changed my design to now require 2 steps: delocate()/relocate(). Delocate
> doesn't know what will be the new address, and relocate doesn't know what
> was the old address. So if an object needs to know (for whatever reason) =
by
> how much it was displaced, it should store the information required durin=
g
> the delocate step and use it in the relocate step.
> These 2 steps makes it possible to tackle the address-space change
> (communication between processes for instance).
>
That's almost true. Your new scheme works at the philosophical level, but
unfortunately does not work at the pragmatic, mathematical level.
Your new scheme is isomorphic to
entireprocess =3D serialize + memcpy + deserialize
which is indeed getting close to some of the stuff people (such as Niall)
have been discussing in other threads. However, your new scheme differs
from traditional serialization libraries in that you are proposing that the
serialized representation of an object must actually fit *within the memory
footprint that the object occupied when it was alive*. This means that
your new scheme cannot handle "near pointers"
struct NearPtr {
uint8_t m_offset;
char *base() const { return intptr_t(this) & ~0xff; }
char *get() const { return base() + m_offset; }
NearPtr(char *p) : m_offset(p - base()) {}
NearPtr(NearPtr&& p) : NearPtr(p.get()) {}
};
because there simply aren't enough bits in the memory footprint of a
NearPtr to actually represent its pointer value!
Although, to be fair, there are other problems
<http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0773r0.html#B> with
trying to use near pointers in C++.
However, I don't plan to standardize this part (I let this part to Nial).
> For now, I will just say that it is undefined behaviour to delocate an
> object without relocating it within the program itself, the same with
> relocating an object that was not delocated in the program.
> We can make it defined behaviour afterwards.
>
No, that's not generally how it works. We shouldn't standardize features
that provide no benefit now, saying that we can always add the benefit
later. We need to see a clear route from where we are now, to the place
where we get the benefit. Your new scheme seems to provide zero benefit,
because:
- It is a no-op on all existing class types, because they don't provide
`operator delocate` or `operator relocate`
- If the programmer opts in by `=3Ddefault`ing those operators, they get th=
e
ability to relocate objects by memcpy
- If the programmer user-provides those operators, they get undefined
behavior (IIUC)
If you think there'd be any situation in which a user-provided `operator
delocate/relocate` would (A) not invoke your above-mentioned "just say that
it is undefined behaviour" and (B) achieve some performance benefit, I'd
like to see you describe that situation.
Concerning your notion of position-independent, I have the feeling that
> this notion would match trivial relocatibility in most cases (all?).
>
No, that's 100% wrong. Look into Boost.Interprocess.
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0Jcj6hniberv3ba-%3Ds-%3DQbaVyrcPTecdG4pEPr=
BhH8p0g%40mail.gmail.com.
--0000000000003b80aa05732d6e76
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sat, Aug 11, 2018 at 1:51 AM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<div class=3D"gmail_extra"><div class=3D"gmail_q=
uote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-">Le samedi 11=
ao=C3=BBt 2018 01:53:41 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-=
width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr">On Friday, August 10, 2018 at 10:19:01 AM UTC-=
7, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">No, I=
was not aware of this very proposal. (That's quite hard to keep track =
of all proposals)<br><br>However, it also shares some issues with most othe=
r proposals.<br>Namely: it talks about destructive move (two different stor=
ages, moving the actual object from one to the other).<br>Also, only trivia=
l destructive moves are considered (no user defined).<br></div></blockquote=
><div><br></div><div>Please elaborate on this last point above ("no us=
er-defined") =E2=80=94 either here, or in private email if you feel mo=
re like it. (I'm the author of P1144 and definitely want to hear if it =
doesn't solve your use-case!)</div></div></blockquote><div><br></div></=
span><div>With your proposal, the user cannot write its own relocation code=
..</div><div>I'll explain it further to answer your other comments direc=
tly.<br></div></div></blockquote><div><br></div><div>Ah. If I understand co=
rrectly, this is merely an artifact of our different definitions of "r=
elocate."</div><div>For my P1144, "relocate =3D move + destroy,&q=
uot; and therefore if you want to customize how your type is "relocate=
d," you just give it a user-provided move-constructor and/or a user-pr=
ovided destructor =E2=80=94 the same thing you already do today.</div><div>=
For your scheme, as originally described, I said it was "relocate =3D =
memcpy + fixup." =C2=A0You have now changed it (good!) to what I would=
call "relocate =3D serialize + memcpy + deserialize." =C2=A0Now =
here's where we crossed wires.=C2=A0 In your old scheme, I was using th=
e term "relocate" to mean the <i>entire</i> operation, but I now =
see that you were using the term "relocate" to mean <i>just the f=
ixup half</i> of the operation.=C2=A0 In your new scheme, I assume, you wou=
ld use the term "relocate" to mean <i>just the deserialize part</=
i> of the operation.</div><div>So I now agree, under your terminology, P114=
4 does not permit the user to define a "relocate" operation, beca=
use P1144 does not admit the existence of any such operation. P1144 doesn&#=
39;t have what I would call a "fixup" or "deserialize" =
step. It <i>only</i> has move plus destroy. You agree that these two operat=
ions are both customizable by the user; you just disagree that either of th=
em, or the combination of both of them, should be known by the word "r=
elocate." =C2=A0I strongly disagree, of course. :)</div><div><br></div=
><div>If you're going to be using the word "relocate" to mean=
<i>just the deserialization step</i> of your three-step process, could you=
please provide a word to refer to the <i>entire</i> three-step process as =
a whole?=C2=A0 I (and Niall AFAIK, and Nicol) have been using the word &quo=
t;relocate" to refer to this <i>entire</i>=C2=A0process =E2=80=94 alth=
ough of course we all disagree as to how many steps the process "reall=
y" has, and what the names of those steps are.</div><div><br></div><di=
v>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(=
204,204,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border=
-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">But my prop=
osal talks about in-place relocation: there is one single storage whose add=
ress has changed.<br>And the relocation can be user-defined (a std::list co=
uld be made nothrow relocatable).<br></div></blockquote><div><br></div><div=
>By P1144's definition, <a href=3D"https://godbolt.org/g/yWBAfK" rel=3D=
"nofollow" target=3D"_blank">std::is_nothrow_relocatable_v<<wbr>std::lis=
t<T>> and not std::is_trivially_relocatable_<wbr>v<std::list<=
;T>></a>.=C2=A0 I think this agrees with your definitions as well, ri=
ght?</div></div></blockquote><div><br></div></span><div>Where we agree is a=
bout what types would be trivially relocatable (our definitions are compati=
ble here).</div><div>However, as we don't share the same definition for=
relocation, not the same types will be nothrow relocatable.</div></div></b=
lockquote><div><br></div><div>Okay, agreed.</div><div>Your old scheme defin=
ed "entireprocess =3D memcpy + relocate" (where I would say "=
;relocate =3D memcpy + fixup").=C2=A0 So for me, "nothrow relocat=
able" means "the entire process is nothrow", whereas for you=
, "nothrow relocatable" means "just the fixup step is nothro=
w."</div><div><br></div><div>However, in your scheme, if the fixup ste=
p is nothrow, then <i>surely</i> the entire process is nothrow!=C2=A0 The m=
emcpy better not throw, right?</div><div><br></div><div>So we ought to agre=
e about the end result: if the entire process (in your scheme) is nothrow, =
then the entire process (in P1144's scheme) is nothrow, because we both=
agree on the starting and ending states for the entire process, regardless=
of whether we call the entire process "relocation" or something =
else.</div><div><br></div><div>But this seems largely irrelevant to the dis=
cussion, so I'd be okay dropping this subject if you are.</div><div><br=
></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-co=
lor:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>For you, if a =
type is movable and destructible, it is relocatable. For me, if there is no=
n-deleted operators delocate/relocate, the type is relocatable.</div><div>S=
o with my design, it is possible to have non-movable non copyable types tha=
t are relocatable (that is probably not a sane default),</div></div></block=
quote><div><br></div><div>Agreed. See=C2=A0<a href=3D"https://quuxplusone.g=
ithub.io/blog/2018/07/06/thoughts-on-sanely-move-assignable/#one-particular=
-kind-of-type-is-o">https://quuxplusone.github.io/blog/2018/07/06/thoughts-=
on-sanely-move-assignable/#one-particular-kind-of-type-is-o</a></div><div><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,2=
04,204);padding-left:1ex"><div dir=3D"ltr"><div> and it is also possible to=
have copyable movable types that are not relocatable.</div></div></blockqu=
ote><div><br></div><div>...because you define "relocatable" to me=
an not just "gettable-from-point-A-to-point-B" but "gettable=
<i>by this specific mechanism</i> involving `operator relocate`." =C2=
=A0So by your definition, IIUC, std::string would not be relocatable at all=
; boost::unique_ptr would not be relocatable at all; folly::FBVector would =
not be relocatable at all...</div><div>This means that you wouldn't be =
able to use "relocatable" as a building block for generic algorit=
hms. Any algorithm that tried to use "operator relocate" internal=
ly would quickly discover that it failed to compile for just about every cl=
ass type in the world, except those that had been specifically designed by =
a C++2a programmer and provided their own "operator relocate".</d=
iv><div><br></div><div>That sounds like a very tough sell.</div><div><br></=
div><div>Contrast that to C++11 move semantics: any copy-constructible C++0=
3 type magically becomes "move-constructible" in C++11 (because t=
he compiler happily uses the copy constructor even on an rvalue).=C2=A0 Con=
trast that to P1144 relocation: any move-constructible, destructible C++11 =
type magically becomes "relocatable" in P1144 (because the librar=
y happily uses the move-constructor and destructor when it detects that mem=
cpy would be inappropriate), and furthermore, many C++11 types magically be=
come "trivially relocatable" in P1144 (because the compiler detec=
ts that they are).</div><div><br></div><div>You seem to be saying that noth=
ing should ever be "efficiently relocatable" unless the programme=
r opts in by implementing `operator relocate` (and now `operator delocate` =
as well).=C2=A0 I don't like that idea. I want to get "efficiently=
relocatable" for free.=C2=A0 That's why P1144.</div><div><br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color=
:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></div><div>I want=
to highlight that some part of your proposal is forward compatible with mi=
ne.</div><div>Namely: which types are trivially relocatible, the fact that =
types following the rule of 0 would get trivial relocability if all its mem=
bers/bases are trivially relocatable, and what is possible to do with trivi=
ally relocatable types.</div><div>Your proposed attribute would also be for=
ward compatible, but redondant.</div></div></blockquote><div><br></div><div=
>IIUC, you'd propose the following general idea:</div><div><br></div><d=
iv>=C2=A0 =C2=A0 template<class T></div><div>=C2=A0 =C2=A0 class RedP=
tr {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 T *m_ptr;<br></div><div>=C2=A0 =
=C2=A0 public:</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 RedPtr(RedPtr&&=
;);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ~RedPtr();</div><div>=C2=A0 =C2=
=A0 };<br></div><div>=C2=A0 =C2=A0 static_assert(not is_florian_relocatable=
_v<RedPtr<int>>);</div><div><div>=C2=A0 =C2=A0 static_assert(no=
t is_florian_trivially_relocatable_v<RedPtr<int>>);</div></div>=
<div><br></div><div><div><div>=C2=A0 =C2=A0 template<class T></div><d=
iv>=C2=A0 =C2=A0 class=C2=A0YellowPtr {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 T *m_ptr;<br></div><div>=C2=A0 =C2=A0 public:</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0=C2=A0YellowPtr(YellowPtr&&);</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 operator delocate() {}</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
operator relocate() {}</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ~YellowPtr();<=
/div><div>=C2=A0 =C2=A0 };<br></div><div>=C2=A0 =C2=A0 static_assert(is_flo=
rian_relocatable_v<YellowPtr<int>>);</div></div><div>=C2=A0 =C2=
=A0 static_assert(not is_florian_trivially_relocatable_v<YellowPtr<in=
t>>);</div><div><br></div><div>=C2=A0 =C2=A0 template<class T><=
/div><div>=C2=A0 =C2=A0 class=C2=A0GreenPtr=C2=A0{</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 T *m_ptr;<br></div><div>=C2=A0 =C2=A0 public:</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0GreenPtr(GreenPtr&&);</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 operator delocate() =3D default;</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 operator relocate() =3D default;</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 ~GreenPtr();</div><div>=C2=A0 =C2=A0 };<br></div><div>=C2=
=A0 =C2=A0 static_assert(is_florian_relocatable_v<GreenPtr<int>>=
;);</div></div><div><div>=C2=A0 =C2=A0 static_assert(is_florian_trivially_r=
elocatable_v<GreenPtr<int>>);</div></div><div><br></div><div><d=
iv><div>(Notice that these Ptr types are intentionally stripped-down versio=
ns of `boost::unique_ptr<T>`.)</div></div></div><div><br></div><div><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,2=
04,204);padding-left:1ex"><div dir=3D"ltr"><div>After all the other comment=
s, I changed my opinion about what should be the relocation.</div><div>Now =
relocation is done in 2 explicit steps: delocate() and relocate().</div><di=
v>Delocate() could be seen as: prepare fixup<br></div><div>Relocate() could=
be seen as: do fixup</div><div>So "relocate(src, dst)" would be =
implemented: src.delocate() + memcpy(dst, src) + dst.relocate().</div><div>=
But yes, my approach is to fix the object after memcpy. (the memcpy might n=
ot happen at all).</div><span class=3D"gmail-"><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div></div><div>In the absolute worst case, "fi=
xup(src,dst)" can be implemented as "move(src,dst) + destroy(src)=
". In the average case, it can be implemented as "fixup-after-mov=
e(dst) + destroy(src)". In the case corresponding to "trivially r=
elocatable", by definition, it can be implemented as a no-op, because =
a trivially relocatable type by definition can be relocated as-if by memcpy=
and therefore requires no extra fixup step <i>after</i> the memcpy.</div><=
/div></blockquote><div><br></div></span><div>I have no "fixup(src, dst=
)".</div></div></blockquote><div><br></div><div>Well, you don't <i=
>now</i>, but you did when I wrote my reply. :D</div><div>Your old scheme r=
equired `operator relocate` to take two parameters: the implicit `this` poi=
nter (pointing to dst) and a `void*` function parameter (pointing to src).<=
/div><div>Your new scheme doesn't require that src parameter at `operat=
or relocate` time; you've replaced it with a src parameter at `operator=
delocate` time.</div><div><br></div><div><br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"ltr"><span class=3D"gmail-"><div>I changed my design to now require 2=
steps: delocate()/relocate(). Delocate doesn't know what will be the n=
ew address, and relocate doesn't know what was the old address. So if a=
n object needs to know (for whatever reason) by how much it was displaced, =
it should store the information required during the delocate step and use i=
t in the relocate step.<br></div></span><div>These 2 steps makes it possibl=
e to tackle the address-space change (communication between processes for i=
nstance).</div></div></blockquote><div><br></div><div>That's almost tru=
e. Your new scheme works at the philosophical level, but unfortunately does=
not work at the pragmatic, mathematical level.</div><div>Your new scheme i=
s isomorphic to</div><div><br></div><div>=C2=A0 =C2=A0 entireprocess =3D se=
rialize + memcpy + deserialize</div><div><br></div><div>which is indeed get=
ting close to some of the stuff people (such as Niall) have been discussing=
in other threads. However, your new scheme differs from traditional serial=
ization libraries in that you are proposing that the serialized representat=
ion of an object must actually fit <i>within the memory footprint that the =
object occupied when it was alive</i>.=C2=A0 This means that your new schem=
e cannot handle "near pointers"</div><div><br></div><div>=C2=A0 =
=C2=A0 struct NearPtr {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint8_t m_off=
set;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 char *base() const { return intp=
tr_t(this) & ~0xff; }</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 char *get()=
const { return base() + m_offset; }</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
NearPtr(char *p) : m_offset(p - base()) {}</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 NearPtr(NearPtr&& p) : NearPtr(p.get()) {}</div><div>=C2=A0 =
=C2=A0 };</div><div><br></div><div>because there simply aren't enough b=
its in the memory footprint of a NearPtr to actually represent its pointer =
value!</div><div>Although, to be fair, there are <a href=3D"http://open-std=
..org/JTC1/SC22/WG21/docs/papers/2017/p0773r0.html#B">other problems</a> wit=
h trying to use near pointers in C++.</div><div><br></div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pad=
ding-left:1ex"><div dir=3D"ltr"><div>However, I don't plan to standardi=
ze this part (I let this part to Nial). For now, I will just say that it is=
undefined behaviour to delocate an object without relocating it within the=
program itself, the same with relocating an object that was not delocated =
in the program.<br></div>We can make it defined behaviour afterwards.<br></=
div></blockquote><div><br></div><div>No, that's not generally how it wo=
rks. We shouldn't standardize features that provide no benefit now, say=
ing that we can always add the benefit later. We need to see a clear route =
from where we are now, to the place where we get the benefit. Your new sche=
me seems to provide zero benefit, because:</div><div>- It is a no-op on all=
existing class types, because they don't provide `operator delocate` o=
r `operator relocate`</div><div>- If the programmer opts in by `=3Ddefault`=
ing those operators, they get the ability to relocate objects by memcpy</di=
v><div>- If the programmer user-provides those operators, they get undefine=
d behavior (IIUC)</div><div><br></div><div>If you think there'd be any =
situation in which a user-provided `operator delocate/relocate` would (A) n=
ot invoke your above-mentioned "just say that it is undefined behaviou=
r" and (B) achieve some performance benefit, I'd like to see you d=
escribe that situation.</div><div><br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b=
order-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"=
><div dir=3D"ltr">Concerning your notion of position-independent, I have th=
e feeling that this notion would match trivial relocatibility in most cases=
(all?).<br></div></blockquote></div><br></div><div class=3D"gmail_extra">N=
o, that's 100% wrong.=C2=A0 Look into Boost.Interprocess.</div><div cla=
ss=3D"gmail_extra"><br></div><div class=3D"gmail_extra">=E2=80=93Arthur</di=
v></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0Jcj6hniberv3ba-%3Ds-%3DQbaVyrc=
PTecdG4pEPrBhH8p0g%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0Jcj6hn=
iberv3ba-%3Ds-%3DQbaVyrcPTecdG4pEPrBhH8p0g%40mail.gmail.com</a>.<br />
--0000000000003b80aa05732d6e76--
.
Author: florian.csdt@gmail.com
Date: Sat, 11 Aug 2018 13:32:25 -0700 (PDT)
Raw View
------=_Part_1114_275209180.1534019545634
Content-Type: multipart/alternative;
boundary="----=_Part_1115_826342258.1534019545636"
------=_Part_1115_826342258.1534019545636
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I see confusion in your answer. My explanations might be a bit confusing so=
=20
I'll try to give clearer explanations.
Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Sat, Aug 11, 2018 at 1:51 AM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>> Le samedi 11 ao=C3=BBt 2018 01:53:41 UTC+2, Arthur O'Dwyer a =C3=A9crit =
:
>>>
>>> On Friday, August 10, 2018 at 10:19:01 AM UTC-7, floria...@gmail.com=20
>>> wrote:
>>>>
>>>> No, I was not aware of this very proposal. (That's quite hard to keep=
=20
>>>> track of all proposals)
>>>>
>>>> However, it also shares some issues with most other proposals.
>>>> Namely: it talks about destructive move (two different storages, movin=
g=20
>>>> the actual object from one to the other).
>>>> Also, only trivial destructive moves are considered (no user defined).
>>>>
>>>
>>> Please elaborate on this last point above ("no user-defined") =E2=80=94=
either=20
>>> here, or in private email if you feel more like it. (I'm the author of=
=20
>>> P1144 and definitely want to hear if it doesn't solve your use-case!)
>>>
>>
>> With your proposal, the user cannot write its own relocation code.
>> I'll explain it further to answer your other comments directly.
>>
>
> Ah. If I understand correctly, this is merely an artifact of our differen=
t=20
> definitions of "relocate."
> For my P1144, "relocate =3D move + destroy," and therefore if you want to=
=20
> customize how your type is "relocated," you just give it a user-provided=
=20
> move-constructor and/or a user-provided destructor =E2=80=94 the same thi=
ng you=20
> already do today.
> For your scheme, as originally described, I said it was "relocate =3D mem=
cpy=20
> + fixup." You have now changed it (good!) to what I would call "relocate=
=3D=20
> serialize + memcpy + deserialize." Now here's where we crossed wires. I=
n=20
> your old scheme, I was using the term "relocate" to mean the *entire*=20
> operation, but I now see that you were using the term "relocate" to mean =
*just=20
> the fixup half* of the operation. In your new scheme, I assume, you=20
> would use the term "relocate" to mean *just the deserialize part* of the=
=20
> operation.
> So I now agree, under your terminology, P1144 does not permit the user to=
=20
> define a "relocate" operation, because P1144 does not admit the existence=
=20
> of any such operation. P1144 doesn't have what I would call a "fixup" or=
=20
> "deserialize" step. It *only* has move plus destroy. You agree that these=
=20
> two operations are both customizable by the user; you just disagree that=
=20
> either of them, or the combination of both of them, should be known by th=
e=20
> word "relocate." I strongly disagree, of course. :)
>
Wording is a tough topic. At the beginning, relocation meant the entire=20
process (but as it was a single step, that was fine). Then, I needed a a=20
second step before the other. And delocate was just the perfect name. But=
=20
now, I don't have any word to mean the entire process... So for now let's=
=20
stick to "full relocation".
So full relocation =3D delocate + moving bytes around (optional) + relocate
=20
>
> If you're going to be using the word "relocate" to mean *just the=20
> deserialization step* of your three-step process, could you please=20
> provide a word to refer to the *entire* three-step process as a whole? I=
=20
> (and Niall AFAIK, and Nicol) have been using the word "relocate" to refer=
=20
> to this *entire* process =E2=80=94 although of course we all disagree as =
to how=20
> many steps the process "really" has, and what the names of those steps ar=
e.
>
> =20
>
>> But my proposal talks about in-place relocation: there is one single=20
>>>> storage whose address has changed.
>>>> And the relocation can be user-defined (a std::list could be made=20
>>>> nothrow relocatable).
>>>>
>>>
>>> By P1144's definition, std::is_nothrow_relocatable_v<std::list<T>> and=
=20
>>> not std::is_trivially_relocatable_v<std::list<T>>=20
>>> <https://godbolt.org/g/yWBAfK>. I think this agrees with your=20
>>> definitions as well, right?
>>>
>>
>> Where we agree is about what types would be trivially relocatable (our=
=20
>> definitions are compatible here).
>> However, as we don't share the same definition for relocation, not the=
=20
>> same types will be nothrow relocatable.
>>
>
> Okay, agreed.
> Your old scheme defined "entireprocess =3D memcpy + relocate" (where I wo=
uld=20
> say "relocate =3D memcpy + fixup"). So for me, "nothrow relocatable" mea=
ns=20
> "the entire process is nothrow", whereas for you, "nothrow relocatable"=
=20
> means "just the fixup step is nothrow."
>
>
As delocate/relocate have no meaning on their own, when I say a type is=20
[trivially|nothrow] relocatable, I mean the entire process is=20
[trivially|nothrow] relocatable.
But some types might not be fully relocatable at all.
=20
> However, in your scheme, if the fixup step is nothrow, then *surely* the=
=20
> entire process is nothrow! The memcpy better not throw, right?
>
Now that the process has 2 steps, the 2 need to be nothrow/trivial for the=
=20
full relocation to be also nothrow/trivial.
I don't consider the memcpy in the middle part of the process. Because that=
=20
might be something completely different from a memcpy.
Actually, nothing at all could happen in the middle, that would still be=20
valid.
=20
>
> So we ought to agree about the end result: if the entire process (in your=
=20
> scheme) is nothrow, then the entire process (in P1144's scheme) is nothro=
w,=20
> because we both agree on the starting and ending states for the entire=20
> process, regardless of whether we call the entire process "relocation" or=
=20
> something else.
>
> But this seems largely irrelevant to the discussion, so I'd be okay=20
> dropping this subject if you are.
>
>
Fair enough.
=20
>
> For you, if a type is movable and destructible, it is relocatable. For me=
,=20
>> if there is non-deleted operators delocate/relocate, the type is=20
>> relocatable.
>> So with my design, it is possible to have non-movable non copyable types=
=20
>> that are relocatable (that is probably not a sane default),
>>
>
> Agreed. See=20
> https://quuxplusone.github.io/blog/2018/07/06/thoughts-on-sanely-move-ass=
ignable/#one-particular-kind-of-type-is-o
>
> and it is also possible to have copyable movable types that are not=20
>> relocatable.
>>
>
> ...because you define "relocatable" to mean not just=20
> "gettable-from-point-A-to-point-B" but "gettable *by this specific=20
> mechanism* involving `operator relocate`."=20
>
Yes, by my definition (but that exactly what I said).
=20
> So by your definition, IIUC, std::string would not be relocatable at all=
;=20
> boost::unique_ptr would not be relocatable at all; folly::FBVector would=
=20
> not be relocatable at all...
>
Of course they would be. Why wouldn't they?
Those are just pointers, and pointers are trivially relocatable. So the=20
compiler generated operators delocate/relocate would also be trivially=20
relocatable.
Maybe that's something I didn't make it clear, but those operations can be=
=20
compiler generated. If there is no user provided operator delocate and all=
=20
members/bases are delocatable, the compiler will generate an operator=20
delocate that will just call those for all subobjects.
Of course, the same applies for the operator relocate.
=20
> This means that you wouldn't be able to use "relocatable" as a building=
=20
> block for generic algorithms. Any algorithm that tried to use "operator=
=20
> relocate" internally would quickly discover that it failed to compile for=
=20
> just about every class type in the world, except those that had been=20
> specifically designed by a C++2a programmer and provided their own=20
> "operator relocate".
>
That's not true, see above.
=20
>
> That sounds like a very tough sell.
>
The way you understood it, I agree that would be very though to sell.
But fortunately, that's not what I propose.
=20
>
> Contrast that to C++11 move semantics: any copy-constructible C++03 type=
=20
> magically becomes "move-constructible" in C++11 (because the compiler=20
> happily uses the copy constructor even on an rvalue). Contrast that to=
=20
> P1144 relocation: any move-constructible, destructible C++11 type magical=
ly=20
> becomes "relocatable" in P1144 (because the library happily uses the=20
> move-constructor and destructor when it detects that memcpy would be=20
> inappropriate), and furthermore, many C++11 types magically become=20
> "trivially relocatable" in P1144 (because the compiler detects that they=
=20
> are).
>
I agree, and that's exactly what I have in mind from the very start (even=
=20
if that wasn't really clear). As I said, most types would have their=20
operator delocate/relocate being auto generated by the compiler. So we are=
=20
in agreement here.
If a type follow the rule of 0, it is completely safe to generate those.=20
Even though, I think that even if the copy/move is user defined, the=20
operators delocate/relocate should still be autogenerated and explicitely=
=20
deleted if that's not correct (which should be really rare).
To be mentionned that if a subobject has a deleted operator=20
delocate/relocate, then the complete object would also have it deleted=20
(same as copy/move).
=20
>
> You seem to be saying that nothing should ever be "efficiently=20
> relocatable" unless the programmer opts in by implementing `operator=20
> relocate` (and now `operator delocate` as well). I don't like that idea.=
I=20
> want to get "efficiently relocatable" for free. That's why P1144.
>
>
And I completely agree with you here: see above.
=20
> =20
>
>> I want to highlight that some part of your proposal is forward compatibl=
e=20
>> with mine.
>> Namely: which types are trivially relocatible, the fact that types=20
>> following the rule of 0 would get trivial relocability if all its=20
>> members/bases are trivially relocatable, and what is possible to do with=
=20
>> trivially relocatable types.
>> Your proposed attribute would also be forward compatible, but redondant.
>>
>
> IIUC, you'd propose the following general idea:
>
> template<class T>
> class RedPtr {
> T *m_ptr;
> public:
> RedPtr(RedPtr&&);
> ~RedPtr();
> };
> static_assert(not is_florian_relocatable_v<RedPtr<int>>);
> static_assert(not is_florian_trivially_relocatable_v<RedPtr<int>>);
>
> template<class T>
> class YellowPtr {
> T *m_ptr;
> public:
> YellowPtr(YellowPtr&&);
> operator delocate() {}
> operator relocate() {}
> ~YellowPtr();
> };
> static_assert(is_florian_relocatable_v<YellowPtr<int>>);
> static_assert(not is_florian_trivially_relocatable_v<YellowPtr<int>>)=
;
>
> template<class T>
> class GreenPtr {
> T *m_ptr;
> public:
> GreenPtr(GreenPtr&&);
> operator delocate() =3D default;
> operator relocate() =3D default;
> ~GreenPtr();
> };
> static_assert(is_florian_relocatable_v<GreenPtr<int>>);
> static_assert(is_florian_trivially_relocatable_v<GreenPtr<int>>);
>
> (Notice that these Ptr types are intentionally stripped-down versions of=
=20
> `boost::unique_ptr<T>`.)
>
>
I agree with the two last versions (YellowPtr and GreenPtr), But I=20
completely disagree with the first one:
template <class T>
class RedPtr /* red like: super green */ {
private:
T* m_ptr;
public:
RedPtr(RedPtr&&);
~RedPtr();
// void operator delocate() =3D default; // autogenerated by the compile=
r
// void operator relocate() =3D default; // autogenerated by the compile=
r
};
static_assert(is_florian_relocatable_v<RedPtr<int>>);
static_assert(is_florian_trivially_relocatable_v<RedPtr<int>>); // int* is=
=20
trivially relocatable so behavior is "inherited"
This would also be true:
struct Foo {
void operator relocate() =3D delete;
};
static_assert(!is_florian_relocatable_v<Foo>);
struct Bar {
Foo foo;
};
static_assert(!is_florian_relocatable_v<Bar>);
=20
>
> After all the other comments, I changed my opinion about what should be=
=20
>> the relocation.
>> Now relocation is done in 2 explicit steps: delocate() and relocate().
>> Delocate() could be seen as: prepare fixup
>> Relocate() could be seen as: do fixup
>> So "relocate(src, dst)" would be implemented: src.delocate() +=20
>> memcpy(dst, src) + dst.relocate().
>> But yes, my approach is to fix the object after memcpy. (the memcpy migh=
t=20
>> not happen at all).
>> =20
>>
>>> In the absolute worst case, "fixup(src,dst)" can be implemented as=20
>>> "move(src,dst) + destroy(src)". In the average case, it can be implemen=
ted=20
>>> as "fixup-after-move(dst) + destroy(src)". In the case corresponding to=
=20
>>> "trivially relocatable", by definition, it can be implemented as a no-o=
p,=20
>>> because a trivially relocatable type by definition can be relocated as-=
if=20
>>> by memcpy and therefore requires no extra fixup step *after* the memcpy=
..
>>>
>>
>> I have no "fixup(src, dst)".
>>
>
> Well, you don't *now*, but you did when I wrote my reply. :D
> Your old scheme required `operator relocate` to take two parameters: the=
=20
> implicit `this` pointer (pointing to dst) and a `void*` function paramete=
r=20
> (pointing to src).
> Your new scheme doesn't require that src parameter at `operator relocate`=
=20
> time; you've replaced it with a src parameter at `operator delocate` time=
..
>
>
> I changed my design to now require 2 steps: delocate()/relocate().=20
>> Delocate doesn't know what will be the new address, and relocate doesn't=
=20
>> know what was the old address. So if an object needs to know (for whatev=
er=20
>> reason) by how much it was displaced, it should store the information=20
>> required during the delocate step and use it in the relocate step.
>> These 2 steps makes it possible to tackle the address-space change=20
>> (communication between processes for instance).
>>
>
> That's almost true. Your new scheme works at the philosophical level, but=
=20
> unfortunately does not work at the pragmatic, mathematical level.
> Your new scheme is isomorphic to
>
> entireprocess =3D serialize + memcpy + deserialize
>
Mostly true: the memcpy in the middle is not actually part of the process.=
=20
And many stuff can happen between delocation and relocation.
=20
>
> which is indeed getting close to some of the stuff people (such as Niall)=
=20
> have been discussing in other threads. However, your new scheme differs=
=20
> from traditional serialization libraries in that you are proposing that t=
he=20
> serialized representation of an object must actually fit *within the=20
> memory footprint that the object occupied when it was alive*.
>
That's exactly that.
=20
> This means that your new scheme cannot handle "near pointers"
>
> struct NearPtr {
> uint8_t m_offset;
> char *base() const { return intptr_t(this) & ~0xff; }
> char *get() const { return base() + m_offset; }
> NearPtr(char *p) : m_offset(p - base()) {}
> NearPtr(NearPtr&& p) : NearPtr(p.get()) {}
> };
>
> because there simply aren't enough bits in the memory footprint of a=20
> NearPtr to actually represent its pointer value!
> Although, to be fair, there are other problems=20
> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0773r0.html#B> with=
=20
> trying to use near pointers in C++.
>
>
Your code looks like an offset pointer whose range is limited. An offset=20
pointer is a tricky question in general.
As long as it points to a subobject of your relocating object, that would=
=20
be exactly what you want. But then, it is not a property of the NearPtr by=
=20
itself, but as part of your object.
So I would say the NearPtr shouldn't relocatable to be safe, but your=20
object could still be relocatable if you want. However, I give no mechanism=
=20
to force your type to be trivially relocatable in that case (like there is=
=20
no way to force trivial copyability).
=20
>
> However, I don't plan to standardize this part (I let this part to Nial).=
=20
>> For now, I will just say that it is undefined behaviour to delocate an=
=20
>> object without relocating it within the program itself, the same with=20
>> relocating an object that was not delocated in the program.
>> We can make it defined behaviour afterwards.
>>
>
> No, that's not generally how it works.
>
I said that's fine because there are many uses cases that it can handle=20
right away other than fully relocating accross processes (see my first=20
post).
We shouldn't standardize features that provide no benefit now, saying that=
=20
> we can always add the benefit later. We need to see a clear route from=20
> where we are now, to the place where we get the benefit. Your new scheme=
=20
> seems to provide zero benefit, because:
> - It is a no-op on all existing class types, because they don't provide=
=20
> `operator delocate` or `operator relocate`
>
Most types would be automatically trivially relocatable (delocate/relocate=
=20
would be generated by the compiler).
=20
> - If the programmer opts in by `=3Ddefault`ing those operators, they get =
the=20
> ability to relocate objects by memcpy
>
=20
A programmer doesn't need to opt-in to get those (unless their type uses=20
non relocatable subobjects).
Also, memcpy is not part of the process.
=20
> - If the programmer user-provides those operators, they get undefined=20
> behavior (IIUC)
>
They don't. Why would they?
They would have UB in the following circumstances:
- An object is delocated but never relocated
- An object is relocated but was not first delocated
- An object delocated once is relocated twice
- An object is delocated twice without relocation in between
- obvious race conditions in mutlithread environment
=20
>
> If you think there'd be any situation in which a user-provided `operator=
=20
> delocate/relocate` would (A) not invoke your above-mentioned "just say th=
at=20
> it is undefined behaviour" and (B) achieve some performance benefit, I'd=
=20
> like to see you describe that situation.
>
>
My "just say it is undefined behaviour" was about delocating an object in=
=20
one process, and relocating it in another process.
Here is an example showing what would be UB, and what would not:
struct Foo {
/* ... */
};
static_assert(is_relocatable_v<Foo>);
int main() {
char* buf1 =3D malloc(sizeof(Foo));
char* buf2 =3D malloc(sizeof(Foo));
Foo* p1 =3D new(buf1) Foo; // object is located as buf1
Foo* p2 =3D reinterpret_cast<Foo*>(buf2); // fine as long as p2 is not=20
dereferenced
// object can be accessed through p1 only and *p2 is UB
p1->operator delocate(); // object has no more location: its bit pattern=
=20
can be moved around
// object cannot be accessed at all and both *p1 and *p2 are UB
// accessing their bytes is fine, though
std::memcpy(buf2, buf1, sizeof(Foo)); // copy the bit pattern from buf1=
=20
to buf2
// object still not accessible, *p1 and *p2 are UB
// accessing their bytes is fine, though
p2->operator relocate(); // object location has been set to buf2
// p1->operator relocate(); // this would be UB
// object is accessible through p2, *p1 is still UB
p2->~Foo(); // destroy the object
free(buf1);
free(buf2);
}
=20
>
> Concerning your notion of position-independent, I have the feeling that=
=20
>> this notion would match trivial relocatibility in most cases (all?).
>>
>
> No, that's 100% wrong. Look into Boost.Interprocess.
>
> =E2=80=93Arthur
>
Ok, pointers are trivially relocatables, though they are not position=20
independant while offset_ptr is.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/4149a2b7-9081-474d-9cfd-81880c28cf30%40isocpp.or=
g.
------=_Part_1115_826342258.1534019545636
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I see confusion in your answer. My explanations might be a=
bit confusing so I'll try to give clearer explanations.<br><br>Le same=
di 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Sat, Aug 1=
1, 2018 at 1:51 AM, <span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"V4oANJ-gDQAJ" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'javascript:';return true;" onclick=3D"this.hre=
f=3D'javascript:';return true;">floria...@gmail.com</a>></span> =
wrote:<div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:soli=
d;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><sp=
an>Le samedi 11 ao=C3=BBt 2018 01:53:41 UTC+2, Arthur O'Dwyer a =C3=A9c=
rit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr">On Friday, August 10, 2018 at 1=
0:19:01 AM UTC-7, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div di=
r=3D"ltr">No, I was not aware of this very proposal. (That's quite hard=
to keep track of all proposals)<br><br>However, it also shares some issues=
with most other proposals.<br>Namely: it talks about destructive move (two=
different storages, moving the actual object from one to the other).<br>Al=
so, only trivial destructive moves are considered (no user defined).<br></d=
iv></blockquote><div><br></div><div>Please elaborate on this last point abo=
ve ("no user-defined") =E2=80=94 either here, or in private email=
if you feel more like it. (I'm the author of P1144 and definitely want=
to hear if it doesn't solve your use-case!)</div></div></blockquote><d=
iv><br></div></span><div>With your proposal, the user cannot write its own =
relocation code.</div><div>I'll explain it further to answer your other=
comments directly.<br></div></div></blockquote><div><br></div><div>Ah. If =
I understand correctly, this is merely an artifact of our different definit=
ions of "relocate."</div><div>For my P1144, "relocate =3D mo=
ve + destroy," and therefore if you want to customize how your type is=
"relocated," you just give it a user-provided move-constructor a=
nd/or a user-provided destructor =E2=80=94 the same thing you already do to=
day.</div><div>For your scheme, as originally described, I said it was &quo=
t;relocate =3D memcpy + fixup." =C2=A0You have now changed it (good!) =
to what I would call "relocate =3D serialize + memcpy + deserialize.&q=
uot; =C2=A0Now here's where we crossed wires.=C2=A0 In your old scheme,=
I was using the term "relocate" to mean the <i>entire</i> operat=
ion, but I now see that you were using the term "relocate" to mea=
n <i>just the fixup half</i> of the operation.=C2=A0 In your new scheme, I =
assume, you would use the term "relocate" to mean <i>just the des=
erialize part</i> of the operation.</div><div>So I now agree, under your te=
rminology, P1144 does not permit the user to define a "relocate" =
operation, because P1144 does not admit the existence of any such operation=
.. P1144 doesn't have what I would call a "fixup" or "des=
erialize" step. It <i>only</i> has move plus destroy. You agree that t=
hese two operations are both customizable by the user; you just disagree th=
at either of them, or the combination of both of them, should be known by t=
he word "relocate." =C2=A0I strongly disagree, of course. :)</div=
></div></div></div></blockquote><div><br></div><div>Wording is a tough topi=
c. At the beginning, relocation meant the entire process (but as it was a s=
ingle step, that was fine). Then, I needed a a second step before the other=
.. And delocate was just the perfect name. But now, I don't have any wor=
d to mean the entire process... So for now let's stick to "full re=
location".</div><div><br></div><div>So full relocation =3D delocate + =
moving bytes around (optional) + relocate<br></div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote"><div><br></div><div>If you're going to be using the word &q=
uot;relocate" to mean <i>just the deserialization step</i> of your thr=
ee-step process, could you please provide a word to refer to the <i>entire<=
/i> three-step process as a whole?=C2=A0 I (and Niall AFAIK, and Nicol) hav=
e been using the word "relocate" to refer to this <i>entire</i>=
=C2=A0process =E2=80=94 although of course we all disagree as to how many s=
teps the process "really" has, and what the names of those steps =
are.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:=
solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"=
><span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204=
,204);padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" =
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:s=
olid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">=
But my proposal talks about in-place relocation: there is one single storag=
e whose address has changed.<br>And the relocation can be user-defined (a s=
td::list could be made nothrow relocatable).<br></div></blockquote><div><br=
></div><div>By P1144's definition, <a href=3D"https://godbolt.org/g/yWB=
AfK" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'htt=
ps://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FyWBAfK\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEvjt6nMc8h1SnuS5LCPd8SYuXdrQ';return t=
rue;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%=
2F%2Fgodbolt.org%2Fg%2FyWBAfK\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEvjt6=
nMc8h1SnuS5LCPd8SYuXdrQ';return true;">std::is_nothrow_relocatable_v<=
;<wbr>std::list<T>> and not std::is_trivially_relocatable_<wbr>v&l=
t;std::list<T>></a>.=C2=A0 I think this agrees with your definitio=
ns as well, right?</div></div></blockquote><div><br></div></span><div>Where=
we agree is about what types would be trivially relocatable (our definitio=
ns are compatible here).</div><div>However, as we don't share the same =
definition for relocation, not the same types will be nothrow relocatable.<=
/div></div></blockquote><div><br></div><div>Okay, agreed.</div><div>Your ol=
d scheme defined "entireprocess =3D memcpy + relocate" (where I w=
ould say "relocate =3D memcpy + fixup").=C2=A0 So for me, "n=
othrow relocatable" means "the entire process is nothrow", w=
hereas for you, "nothrow relocatable" means "just the fixup =
step is nothrow."</div><div><br></div></div></div></div></blockquote><=
div><br></div><div>As delocate/relocate have no meaning on their own, when =
I say a type is [trivially|nothrow] relocatable, I mean the entire process =
is [trivially|nothrow] relocatable.</div><div>But some types might not be f=
ully relocatable at all.<br></div><div>=C2=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=
</div><div>However, in your scheme, if the fixup step is nothrow, then <i>s=
urely</i> the entire process is nothrow!=C2=A0 The memcpy better not throw,=
right?</div></div></div></div></blockquote><div><br></div><div>Now that th=
e process has 2 steps, the 2 need to be nothrow/trivial for the full reloca=
tion to be also nothrow/trivial.</div><div>I don't consider the memcpy =
in the middle part of the process. Because that might be something complete=
ly different from a memcpy.</div><div>Actually, nothing at all could happen=
in the middle, that would still be valid.<br></div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"=
gmail_quote"><div><br></div><div>So we ought to agree about the end result:=
if the entire process (in your scheme) is nothrow, then the entire process=
(in P1144's scheme) is nothrow, because we both agree on the starting =
and ending states for the entire process, regardless of whether we call the=
entire process "relocation" or something else.</div><div><br></d=
iv><div>But this seems largely irrelevant to the discussion, so I'd be =
okay dropping this subject if you are.</div><div><br></div></div></div></di=
v></blockquote><div><br></div><div>Fair enough.<br></div><div>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><div></div><div><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-styl=
e:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"lt=
r"><div>For you, if a type is movable and destructible, it is relocatable. =
For me, if there is non-deleted operators delocate/relocate, the type is re=
locatable.</div><div>So with my design, it is possible to have non-movable =
non copyable types that are relocatable (that is probably not a sane defaul=
t),</div></div></blockquote><div><br></div><div>Agreed. See=C2=A0<a href=3D=
"https://quuxplusone.github.io/blog/2018/07/06/thoughts-on-sanely-move-assi=
gnable/#one-particular-kind-of-type-is-o" target=3D"_blank" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%=
2F%2Fquuxplusone.github.io%2Fblog%2F2018%2F07%2F06%2Fthoughts-on-sanely-mov=
e-assignable%2F%23one-particular-kind-of-type-is-o\x26sa\x3dD\x26sntz\x3d1\=
x26usg\x3dAFQjCNE2vwCdViIN3U1FA_2qYi4uFxgH3A';return true;" onclick=3D"=
this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.=
github.io%2Fblog%2F2018%2F07%2F06%2Fthoughts-on-sanely-move-assignable%2F%2=
3one-particular-kind-of-type-is-o\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE=
2vwCdViIN3U1FA_2qYi4uFxgH3A';return true;">https://quuxplusone.<wbr>git=
hub.io/blog/2018/07/06/<wbr>thoughts-on-sanely-move-<wbr>assignable/#one-pa=
rticular-<wbr>kind-of-type-is-o</a></div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div> and it is also possible to have copyable movable typ=
es that are not relocatable.</div></div></blockquote><div><br></div><div>..=
..because you define "relocatable" to mean not just "gettable=
-from-point-A-to-<wbr>point-B" but "gettable <i>by this specific =
mechanism</i> involving `operator relocate`." </div></div></div></div>=
</blockquote><div><br></div><div>Yes, by my definition (but that exactly wh=
at I said).<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=C2=A0So by y=
our definition, IIUC, std::string would not be relocatable at all; boost::u=
nique_ptr would not be relocatable at all; folly::FBVector would not be rel=
ocatable at all...</div></div></div></div></blockquote><div><br></div><div>=
Of course they would be. Why wouldn't they?</div><div>Those are just po=
inters, and pointers are trivially relocatable. So the compiler generated o=
perators delocate/relocate would also be trivially relocatable.</div><div>M=
aybe that's something I didn't make it clear, but those operations =
can be compiler generated. If there is no user provided operator delocate a=
nd all members/bases are delocatable, the compiler will generate an operato=
r delocate that will just call those for all subobjects.</div><div>Of cours=
e, the same applies for the operator relocate.</div><div><br></div><div><br=
></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div>This means that you wouldn&=
#39;t be able to use "relocatable" as a building block for generi=
c algorithms. Any algorithm that tried to use "operator relocate"=
internally would quickly discover that it failed to compile for just about=
every class type in the world, except those that had been specifically des=
igned by a C++2a programmer and provided their own "operator relocate&=
quot;.</div></div></div></div></blockquote><div><br></div><div>That's n=
ot true, see above.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br><=
/div><div>That sounds like a very tough sell.</div></div></div></div></bloc=
kquote><div><br></div><div>The way you understood it, I agree that would be=
very though to sell.</div><div>But fortunately, that's not what I prop=
ose.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>Contr=
ast that to C++11 move semantics: any copy-constructible C++03 type magical=
ly becomes "move-constructible" in C++11 (because the compiler ha=
ppily uses the copy constructor even on an rvalue).=C2=A0 Contrast that to =
P1144 relocation: any move-constructible, destructible C++11 type magically=
becomes "relocatable" in P1144 (because the library happily uses=
the move-constructor and destructor when it detects that memcpy would be i=
nappropriate), and furthermore, many C++11 types magically become "tri=
vially relocatable" in P1144 (because the compiler detects that they a=
re).</div></div></div></div></blockquote><div><br></div><div>I agree, and t=
hat's exactly what I have in mind from the very start (even if that was=
n't really clear). As I said, most types would have their operator delo=
cate/relocate being auto generated by the compiler. So we are in agreement =
here.</div><div>If a type follow the rule of 0, it is completely safe to ge=
nerate those. Even though, I think that even if the copy/move is user defin=
ed, the operators delocate/relocate should still be autogenerated and expli=
citely deleted if that's not correct (which should be really rare).</di=
v><div>To be mentionned that if a subobject has a deleted operator delocate=
/relocate, then the complete object would also have it deleted (same as cop=
y/move).<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>=
You seem to be saying that nothing should ever be "efficiently relocat=
able" unless the programmer opts in by implementing `operator relocate=
` (and now `operator delocate` as well).=C2=A0 I don't like that idea. =
I want to get "efficiently relocatable" for free.=C2=A0 That'=
s why P1144.</div><div><br></div></div></div></div></blockquote><div><br></=
div><div>And I completely agree with you here: see above.<br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
><div class=3D"gmail_quote"><div></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div></div><div>I want to highlight that some part of your=
proposal is forward compatible with mine.</div><div>Namely: which types ar=
e trivially relocatible, the fact that types following the rule of 0 would =
get trivial relocability if all its members/bases are trivially relocatable=
, and what is possible to do with trivially relocatable types.</div><div>Yo=
ur proposed attribute would also be forward compatible, but redondant.</div=
></div></blockquote><div><br></div><div>IIUC, you'd propose the followi=
ng general idea:</div><div><br></div><div>=C2=A0 =C2=A0 template<class T=
></div><div>=C2=A0 =C2=A0 class RedPtr {</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 T *m_ptr;<br></div><div>=C2=A0 =C2=A0 public:</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 RedPtr(RedPtr&&);</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 ~RedPtr();</div><div>=C2=A0 =C2=A0 };<br></div><div>=C2=A0 =C2=A0 st=
atic_assert(not is_florian_relocatable_v<<wbr>RedPtr<int>>);</d=
iv><div><div>=C2=A0 =C2=A0 static_assert(not is_florian_trivially_<wbr>relo=
catable_v<RedPtr<int>>);</div></div><div><br></div><div><div><d=
iv>=C2=A0 =C2=A0 template<class T></div><div>=C2=A0 =C2=A0 class=C2=
=A0YellowPtr {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 T *m_ptr;<br></div><di=
v>=C2=A0 =C2=A0 public:</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0YellowPt=
r(YellowPtr&&);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 operator delo=
cate() {}</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 operator relocate() {}</div=
><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ~YellowPtr();</div><div>=C2=A0 =C2=A0 };<=
br></div><div>=C2=A0 =C2=A0 static_assert(is_florian_<wbr>relocatable_v<=
YellowPtr<int>>)<wbr>;</div></div><div>=C2=A0 =C2=A0 static_assert=
(not is_florian_trivially_<wbr>relocatable_v<YellowPtr<int>>)<w=
br>;</div><div><br></div><div>=C2=A0 =C2=A0 template<class T></div><d=
iv>=C2=A0 =C2=A0 class=C2=A0GreenPtr=C2=A0{</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 T *m_ptr;<br></div><div>=C2=A0 =C2=A0 public:</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0=C2=A0GreenPtr(GreenPtr&&);</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 operator delocate() =3D default;</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 operator relocate() =3D default;</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 ~GreenPtr();</div><div>=C2=A0 =C2=A0 };<br></div><div>=C2=A0 =C2=
=A0 static_assert(is_florian_<wbr>relocatable_v<GreenPtr<int>>)=
;</div></div><div><div>=C2=A0 =C2=A0 static_assert(is_florian_<wbr>triviall=
y_relocatable_v<<wbr>GreenPtr<int>>);</div></div><div><br></div=
><div><div><div>(Notice that these Ptr types are intentionally stripped-dow=
n versions of `boost::unique_ptr<T>`.)</div></div></div><div><br></di=
v></div></div></div></blockquote><div><br></div><div>I agree with the two l=
ast versions (YellowPtr and GreenPtr), But I completely disagree with the f=
irst one:</div><div><div style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; over=
flow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">template</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">class=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">></span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">RedPtr</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">/* red like: super green */</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">private</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 =C2=A0 T</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> m_ptr</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">pub=
lic</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">RedPtr=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">RedPtr</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&&);</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">~</span><span=
style=3D"color: #606;" class=3D"styled-by-prettify">RedPtr</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0</span><span=
style=3D"color: #800;" class=3D"styled-by-prettify">// void operator deloc=
ate() =3D default; // autogenerated by the compiler</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span styl=
e=3D"color: #800;" class=3D"styled-by-prettify">// void operator relocate()=
=3D default; // autogenerated by the compiler</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">static_assert</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">is_florian_relocatable_v</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">RedPtr</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><int></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">>);</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">static_assert</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">is_florian_trivially_relocatable_v</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify"><</span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">RedPtr</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><int></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">>);</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-b=
y-prettify">// int* is trivially relocatable so behavior is "inherited=
"</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span></div></code></div></div><br>This would also be true:<div><div style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; overflow-wrap: break-word;" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">operator</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> relocate</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">delete</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">static_assert</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(!</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">is_florian_relocatable_v</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">>);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Bar</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">static_assert</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(!</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>is_florian_relocatable_v</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Bar</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">>);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span></div></code></div><br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><=
div></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left=
-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>After all t=
he other comments, I changed my opinion about what should be the relocation=
..</div><div>Now relocation is done in 2 explicit steps: delocate() and relo=
cate().</div><div>Delocate() could be seen as: prepare fixup<br></div><div>=
Relocate() could be seen as: do fixup</div><div>So "relocate(src, dst)=
" would be implemented: src.delocate() + memcpy(dst, src) + dst.reloca=
te().</div><div>But yes, my approach is to fix the object after memcpy. (th=
e memcpy might not happen at all).</div><span><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr"><div></div><div>In the absolute worst case, "fix=
up(src,dst)" can be implemented as "move(src,dst) + destroy(src)&=
quot;. In the average case, it can be implemented as "fixup-after-move=
(dst) + destroy(src)". In the case corresponding to "trivially re=
locatable", by definition, it can be implemented as a no-op, because a=
trivially relocatable type by definition can be relocated as-if by memcpy =
and therefore requires no extra fixup step <i>after</i> the memcpy.</div></=
div></blockquote><div><br></div></span><div>I have no "fixup(src, dst)=
".</div></div></blockquote><div><br></div><div>Well, you don't <i>=
now</i>, but you did when I wrote my reply. :D</div><div>Your old scheme re=
quired `operator relocate` to take two parameters: the implicit `this` poin=
ter (pointing to dst) and a `void*` function parameter (pointing to src).</=
div><div>Your new scheme doesn't require that src parameter at `operato=
r relocate` time; you've replaced it with a src parameter at `operator =
delocate` time.</div><div><br></div><div><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div di=
r=3D"ltr"><span><div>I changed my design to now require 2 steps: delocate()=
/relocate(). Delocate doesn't know what will be the new address, and re=
locate doesn't know what was the old address. So if an object needs to =
know (for whatever reason) by how much it was displaced, it should store th=
e information required during the delocate step and use it in the relocate =
step.<br></div></span><div>These 2 steps makes it possible to tackle the ad=
dress-space change (communication between processes for instance).</div></d=
iv></blockquote><div><br></div><div>That's almost true. Your new scheme=
works at the philosophical level, but unfortunately does not work at the p=
ragmatic, mathematical level.</div><div>Your new scheme is isomorphic to</d=
iv><div><br></div><div>=C2=A0 =C2=A0 entireprocess =3D serialize + memcpy +=
deserialize</div></div></div></div></blockquote><div><br></div><div>Mostly=
true: the memcpy in the middle is not actually part of the process. And ma=
ny stuff can happen between delocation and relocation.<br></div><div>=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote"><div><br></div><div>which is indeed getting close =
to some of the stuff people (such as Niall) have been discussing in other t=
hreads. However, your new scheme differs from traditional serialization lib=
raries in that you are proposing that the serialized representation of an o=
bject must actually fit <i>within the memory footprint that the object occu=
pied when it was alive</i>.</div></div></div></div></blockquote><div><br></=
div><div>That's exactly that.<br></div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quo=
te"><div>This means that your new scheme cannot handle "near pointers&=
quot;</div><div><br></div><div>=C2=A0 =C2=A0 struct NearPtr {</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 uint8_t m_offset;</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 char *base() const { return intptr_t(this) & ~0xff; }</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 char *get() const { return base() + m_offset; }=
</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 NearPtr(char *p) : m_offset(p - base=
()) {}</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 NearPtr(NearPtr&& p) :=
NearPtr(p.get()) {}</div><div>=C2=A0 =C2=A0 };</div><div><br></div><div>be=
cause there simply aren't enough bits in the memory footprint of a Near=
Ptr to actually represent its pointer value!</div><div>Although, to be fair=
, there are <a href=3D"http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/=
p0773r0.html#B" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.org%2FJTC1%2FS=
C22%2FWG21%2Fdocs%2Fpapers%2F2017%2Fp0773r0.html%23B\x26sa\x3dD\x26sntz\x3d=
1\x26usg\x3dAFQjCNHfZD7sl6qp45GSF59oW5lKd79Y9g';return true;" onclick=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.o=
rg%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2017%2Fp0773r0.html%23B\x26sa\x3d=
D\x26sntz\x3d1\x26usg\x3dAFQjCNHfZD7sl6qp45GSF59oW5lKd79Y9g';return tru=
e;">other problems</a> with trying to use near pointers in C++.</div><div><=
br></div></div></div></div></blockquote><div><br></div><div>Your code looks=
like an offset pointer whose range is limited. An offset pointer is a tric=
ky question in general.<br></div><div>As long as it points to a subobject o=
f your relocating object, that would be exactly what you want. But then, it=
is not a property of the NearPtr by itself, but as part of your object.</d=
iv><div>So I would say the NearPtr shouldn't relocatable to be safe, bu=
t your object could still be relocatable if you want. However, I give no me=
chanism to force your type to be trivially relocatable in that case (like t=
here is no way to force trivial copyability).<br></div><div>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div></div><div><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style=
:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div>However, I don't plan to standardize this part (I let this part =
to Nial). For now, I will just say that it is undefined behaviour to deloca=
te an object without relocating it within the program itself, the same with=
relocating an object that was not delocated in the program.<br></div>We ca=
n make it defined behaviour afterwards.<br></div></blockquote><div><br></di=
v><div>No, that's not generally how it works.</div></div></div></div></=
blockquote><div><br></div><div>I said that's fine because there are man=
y uses cases that it can handle right away other than fully relocating accr=
oss processes (see my first post).<br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quot=
e"><div>We shouldn't standardize features that provide no benefit now, =
saying that we can always add the benefit later. We need to see a clear rou=
te from where we are now, to the place where we get the benefit. Your new s=
cheme seems to provide zero benefit, because:</div><div>- It is a no-op on =
all existing class types, because they don't provide `operator delocate=
` or `operator relocate`</div></div></div></div></blockquote><div><br></div=
><div>Most types would be automatically trivially relocatable (delocate/rel=
ocate would be generated by the compiler).<br></div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"=
gmail_quote"><div>- If the programmer opts in by `=3Ddefault`ing those oper=
ators, they get the ability to relocate objects by memcpy</div></div></div>=
</div></blockquote><div>=C2=A0</div><div>A programmer doesn't need to o=
pt-in to get those (unless their type uses non relocatable subobjects).</di=
v><div><br></div><div>Also, memcpy is not part of the process.<br></div><di=
v>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div><div class=3D"gmail_quote"><div>- If the programmer user-provides tho=
se operators, they get undefined behavior (IIUC)</div></div></div></div></b=
lockquote><div><br></div><div>They don't. Why would they?</div><div><br=
></div><div>They would have UB in the following circumstances:</div><div>- =
An object is delocated but never relocated</div><div>- An object is relocat=
ed but was not first delocated</div><div>- An object delocated once is relo=
cated twice</div><div>- An object is delocated twice without relocation in =
between</div><div>- obvious race conditions in mutlithread environment<br><=
/div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>If you think t=
here'd be any situation in which a user-provided `operator delocate/rel=
ocate` would (A) not invoke your above-mentioned "just say that it is =
undefined behaviour" and (B) achieve some performance benefit, I'd=
like to see you describe that situation.</div><div><br></div></div></div><=
/div></blockquote><div><br></div><div>My "just say it is undefined beh=
aviour" was about delocating an object in one process, and relocating =
it in another process.</div><div><br></div><div>Here is an example showing =
what would be UB, and what would not:</div><div><div style=3D"background-co=
lor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: so=
lid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">/* ... */</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">static_assert</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">is_relocatable_v</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">>);</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> main</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>char</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> buf1 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> malloc</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">char</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bu=
f2 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> malloc</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">));</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #606;" =
class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> p1 </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">buf1</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" =
class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// object is located as buf1</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> p2 </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_c=
ast</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">*>(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">buf2</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;"=
class=3D"styled-by-prettify">// fine as long as p2 is not dereferenced</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0=
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// object=
can be accessed through p1 only and *p2 is UB</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br><br>=C2=A0 p1</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">-></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> delocate</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// object has no more location: its bit pattern can be m=
oved around</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// object cannot be accessed at all and both *p1 and *p2 are UB</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">// accessing th=
eir bytes is fine, though</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br><br>=C2=A0 std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">memcpy</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">buf2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> buf1</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">// copy the bit pattern from buf1 to buf2</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"col=
or: #800;" class=3D"styled-by-prettify">// object still not accessible, *p1=
and *p2 are UB</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// accessing their bytes is fine, though</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br><br>=C2=A0 p2</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">-></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> relocate</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// object location has been set to buf2</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span=
style=3D"color: #800;" class=3D"styled-by-prettify">// p1->operator rel=
ocate(); // this would be UB</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// object is accessible through p2, *p1 is still UB=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=
=C2=A0 p2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-=
>~</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// destroy the object</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 fr=
ee</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">buf1</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 free</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">buf2</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span></div></code></div><br><br></div><div>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div></div><div><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style=
:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
">Concerning your notion of position-independent, I have the feeling that t=
his notion would match trivial relocatibility in most cases (all?).<br></di=
v></blockquote></div><br></div><div>No, that's 100% wrong.=C2=A0 Look i=
nto Boost.Interprocess.</div><div><br></div><div>=E2=80=93Arthur</div></div=
></blockquote><div><br></div><div>Ok, pointers are trivially relocatables, =
though they are not position independant while offset_ptr is.<br></div></di=
v>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4149a2b7-9081-474d-9cfd-81880c28cf30%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4149a2b7-9081-474d-9cfd-81880c28cf30=
%40isocpp.org</a>.<br />
------=_Part_1115_826342258.1534019545636--
------=_Part_1114_275209180.1534019545634--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sat, 11 Aug 2018 17:02:53 -0700
Raw View
--000000000000cad19e057331b2d0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sat, Aug 11, 2018 at 1:32 PM, <florian.csdt@gmail.com> wrote:
> Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>
>>
>> Ah. If I understand correctly, this is merely an artifact of our
>> different definitions of "relocate."
>> For my P1144, "relocate =3D move + destroy," and therefore if you want t=
o
>> customize how your type is "relocated," you just give it a user-provided
>> move-constructor and/or a user-provided destructor =E2=80=94 the same th=
ing you
>> already do today.
>> For your scheme, as originally described, I said it was "relocate =3D
>> memcpy + fixup." You have now changed it (good!) to what I would call
>> "relocate =3D serialize + memcpy + deserialize." Now here's where we cr=
ossed
>> wires. In your old scheme, I was using the term "relocate" to mean the
>> *entire* operation, but I now see that you were using the term
>> "relocate" to mean *just the fixup half* of the operation. In your new
>> scheme, I assume, you would use the term "relocate" to mean *just the
>> deserialize part* of the operation.
>> So I now agree, under your terminology, P1144 does not permit the user t=
o
>> define a "relocate" operation, because P1144 does not admit the existenc=
e
>> of any such operation. P1144 doesn't have what I would call a "fixup" or
>> "deserialize" step. It *only* has move plus destroy. You agree that
>> these two operations are both customizable by the user; you just disagre=
e
>> that either of them, or the combination of both of them, should be known=
by
>> the word "relocate." I strongly disagree, of course. :)
>>
>
> Wording is a tough topic. At the beginning, relocation meant the entire
> process (but as it was a single step, that was fine). Then, I needed a a
> second step before the other. And delocate was just the perfect name. But
> now, I don't have any word to mean the entire process... So for now let's
> stick to "full relocation".
>
> So full relocation =3D delocate + moving bytes around (optional) + reloca=
te
>
Please find a verb that describes the entire process. In English (and
standardese) you can't have the relationship
$adverb $verb1 :=3D something + something + $verb1
That is, "full relocation" must by definition be *a kind of* "relocation."
(What kind of relocation? Full relocation.)
You can't have "full relocation" meaning "relocation, but with two
additional steps on the front that do not happen during any other kind of
relocation."
Compare: "Trivial relocation" means relocation that is trivial.
"Nothrow relocation" means relocation that is nothrow.
(And in my last response, "efficient relocation" meant "relocation that is
efficient.")
So for this message (and this message only), I'll use the verb
"fullrelocate" as meaning "delocate + memcpy + relocate", but I'm not going
to use that verb any more after that.
I strongly, strongly suggest that you adopt the verb "relocate" as meaning
"deserialize + memcpy + serialize" (that is, replace your "operator
relocate" with an "operator serialize"). That will bring your terminology
into line with the terminology that has been established in previous
discussions in this forum (by myself, Nicol, Niall, Facebook Folly, EASTL,
etc.)
[...]
> Okay, agreed.
>> Your old scheme defined "entireprocess =3D memcpy + relocate" (where I
>> would say "relocate =3D memcpy + fixup"). So for me, "nothrow relocatab=
le"
>> means "the entire process is nothrow", whereas for you, "nothrow
>> relocatable" means "just the fixup step is nothrow."
>>
>
> As delocate/relocate have no meaning on their own, when I say a type is
> [trivially|nothrow] relocatable, I mean the entire process is
> [trivially|nothrow] relocatable.
>
Again, that's not how English works. "Trivially relocatable" *by definition=
*
means that the relocate operation, the relocation, is trivial. You are
allowed to make up words, but you still have to put them together in the
ways that have been established for communication over the past ~2000 years=
..
Also, it doesn't make any sense to say that a "process" is trivially
relocatable. I infer that you meant to say *the entire process of
fullrelocation is [trivial|nothrow]*.
The way you'd express that concisely in English is "the type is
[trivially|nothrow] fullrelocatable." This is why it's important to have a
word for the entire process! (And we do: everyone but you calls the entire
process by the word "relocation.")
and it is also possible to have copyable movable types that are not
>>> relocatable.
>>>
>>
>> ...because you define "relocatable" to mean not just
>> "gettable-from-point-A-to-point-B" but "gettable *by this specific
>> mechanism* involving `operator relocate`."
>>
> So by your definition, IIUC, std::string would not be relocatable at all=
;
>> boost::unique_ptr would not be relocatable at all; folly::FBVector would
>> not be relocatable at all...
>>
>
> Of course they would be. Why wouldn't they?
> Those are just pointers, and pointers are trivially relocatable. So the
> compiler generated operators delocate/relocate would also be trivially
> relocatable.
>
Please explain how you propose to do this for boost::unique_ptr, without
completely breaking std::list.
Appendix C of P1144
<http://quuxplusone.github.io/draft/d1144-object-relocation.html#non-trivia=
l-samples>
will be useful to you; it lists four situations that can make a type
non-trivially relocatable.
I agree with the two last versions (YellowPtr and GreenPtr), But I
> completely disagree with the first one:
> template <class T>
> class RedPtr /* red like: super green */ {
> private:
> T* m_ptr;
> public:
> RedPtr(RedPtr&&);
> ~RedPtr();
>
> // void operator delocate() =3D default; // autogenerated by the compi=
ler
> // void operator relocate() =3D default; // autogenerated by the compi=
ler
> };
>
> static_assert(is_florian_relocatable_v<RedPtr<int>>);
> static_assert(is_florian_trivially_relocatable_v<RedPtr<int>>); // int*
> is trivially relocatable so behavior is "inherited"
>
You are proposing that this type should be considered trivially
fullrelocatable, even though the compiler has no idea what its move
constructor and destructor do.
Please explain, in the form of a code sample, how you envision a library
would take advantage of the fullrelocation operation to speed up a common
operation (such as std::vector::resize or std::swap =E2=80=94 but I'll acce=
pt
different examples too). Remember, your library is not allowed to segfault
when presented with std::list.
Your code looks like an offset pointer whose range is limited. An offset
> pointer is a tricky question in general.
>
Yes, it is. Does your proposed library segfault when presented with
offset_ptr? P1144 does not.
So I would say the NearPtr shouldn't relocatable to be safe
>
Please describe how your compiler would ensure that NearPtr was *not*
considered trivially fullrelocatable, *yet, at the same time*, ensure that
RedPtr was considered trivially fullrelocatable.
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0%2BsDmOqNrV0GFdeDcoBVsz4%2BQD4xrAMxwuC%3D=
c9AOn5Qtg%40mail.gmail.com.
--000000000000cad19e057331b2d0
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sat, Aug 11, 2018 at 1:32 PM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr">Le samedi 11 ao=C3=BBt 2018 20:=
57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span class=3D"gmail-"><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pa=
dding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br><=
/div><div>Ah. If I understand correctly, this is merely an artifact of our =
different definitions of "relocate."</div><div>For my P1144, &quo=
t;relocate =3D move + destroy," and therefore if you want to customize=
how your type is "relocated," you just give it a user-provided m=
ove-constructor and/or a user-provided destructor =E2=80=94 the same thing =
you already do today.</div><div>For your scheme, as originally described, I=
said it was "relocate =3D memcpy + fixup." =C2=A0You have now ch=
anged it (good!) to what I would call "relocate =3D serialize + memcpy=
+ deserialize." =C2=A0Now here's where we crossed wires.=C2=A0 In=
your old scheme, I was using the term "relocate" to mean the <i>=
entire</i> operation, but I now see that you were using the term "relo=
cate" to mean <i>just the fixup half</i> of the operation.=C2=A0 In yo=
ur new scheme, I assume, you would use the term "relocate" to mea=
n <i>just the deserialize part</i> of the operation.</div><div>So I now agr=
ee, under your terminology, P1144 does not permit the user to define a &quo=
t;relocate" operation, because P1144 does not admit the existence of a=
ny such operation. P1144 doesn't have what I would call a "fixup&q=
uot; or "deserialize" step. It <i>only</i> has move plus destroy.=
You agree that these two operations are both customizable by the user; you=
just disagree that either of them, or the combination of both of them, sho=
uld be known by the word "relocate." =C2=A0I strongly disagree, o=
f course. :)</div></div></div></div></blockquote><div><br></div></span><div=
>Wording is a tough topic. At the beginning, relocation meant the entire pr=
ocess (but as it was a single step, that was fine). Then, I needed a a seco=
nd step before the other. And delocate was just the perfect name. But now, =
I don't have any word to mean the entire process... So for now let'=
s stick to "full relocation".</div><div><br></div><div>So full re=
location =3D delocate + moving bytes around (optional) + relocate<br></div>=
</div></blockquote><div><br></div><div>Please find a verb that describes th=
e entire process. In English (and standardese) you can't have the relat=
ionship</div><div><br></div><div>=C2=A0 =C2=A0 $adverb $verb1 :=3D somethin=
g + something + $verb1</div><div><br></div><div>That is, "full relocat=
ion" must by definition be <i>a kind of</i> "relocation." (W=
hat kind of relocation? Full relocation.)</div><div>You can't have &quo=
t;full relocation" meaning "relocation, but with two additional s=
teps on the front that do not happen during any other kind of relocation.&q=
uot;</div><div><br></div><div>Compare: "Trivial relocation" means=
relocation that is trivial.</div><div>"Nothrow relocation" means=
relocation that is nothrow.</div><div>(And in my last response, "effi=
cient relocation" meant "relocation that is efficient.")</di=
v><div><br></div><div>So for this message (and this message only), I'll=
use the verb "fullrelocate" as meaning "delocate + memcpy +=
relocate", but I'm not going to use that verb any more after that=
..</div><div><br></div><div>I strongly, strongly suggest that you adopt the =
verb "relocate" as meaning "deserialize + memcpy + serialize=
" (that is, replace your "operator relocate" with an "o=
perator serialize"). That will bring your terminology into line with t=
he terminology that has been established in previous discussions in this fo=
rum (by myself, Nicol, Niall, Facebook Folly, EASTL, etc.)</div><div><br></=
div><div>[...]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-colo=
r:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-=
"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204)=
;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div>Okay, a=
greed.<br></div><div>Your old scheme defined "entireprocess =3D memcpy=
+ relocate" (where I would say "relocate =3D memcpy + fixup"=
;).=C2=A0 So for me, "nothrow relocatable" means "the entire=
process is nothrow", whereas for you, "nothrow relocatable"=
means "just the fixup step is nothrow."</div></div></div></block=
quote><div><br></div></span><div>As delocate/relocate have no meaning on th=
eir own, when I say a type is [trivially|nothrow] relocatable, I mean the e=
ntire process is [trivially|nothrow] relocatable.</div></div></blockquote><=
div><br></div><div>Again, that's not how English works. "Trivially=
relocatable" <i>by definition</i> means that the relocate operation, =
the relocation, is trivial. You are allowed to make up words, but you still=
have to put them together in the ways that have been established for commu=
nication over the past ~2000 years.</div><div><br></div><div>Also, it doesn=
't make any sense to say that a "process" is trivially reloca=
table.=C2=A0 I infer that you meant to say <i>the entire process of fullrel=
ocation is [trivial|nothrow]</i>.</div><div>The way you'd express that =
concisely in English is "the type is [trivially|nothrow] fullrelocatab=
le." =C2=A0This is why it's important to have a word for the entir=
e process! =C2=A0(And we do: everyone but you calls the entire process by t=
he word "relocation.")</div><div><br></div><div><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-=
left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" =
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:s=
olid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">=
<div> and it is also possible to have copyable movable types that are not r=
elocatable.</div></div></blockquote><div><br></div><div>...because you defi=
ne "relocatable" to mean not just "gettable-from-point-A-to-=
poin<wbr>t-B" but "gettable <i>by this specific mechanism</i> inv=
olving `operator relocate`."</div></div></div></div></blockquote></spa=
n><span class=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left=
-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div>=C2=A0So by your definition, IIUC, std::string would =
not be relocatable at all; boost::unique_ptr would not be relocatable at al=
l; folly::FBVector would not be relocatable at all...</div></div></div></di=
v></blockquote><div><br></div></span><div>Of course they would be. Why woul=
dn't they?</div><div>Those are just pointers, and pointers are triviall=
y relocatable. So the compiler generated operators delocate/relocate would =
also be trivially relocatable.</div></div></blockquote><div><br></div><div>=
Please explain how you propose to do this for boost::unique_ptr, without co=
mpletely breaking std::list.</div><div><a href=3D"http://quuxplusone.github=
..io/draft/d1144-object-relocation.html#non-trivial-samples">Appendix C of P=
1144</a> will be useful to you; it lists four situations that can make a ty=
pe non-trivially relocatable.</div><div><br></div><div><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width=
:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-lef=
t:1ex"><div dir=3D"ltr"><div><div class=3D"gmail-h5"><div><span style=3D"co=
lor:rgb(34,34,34)">I agree with the two last versions (YellowPtr and GreenP=
tr), But I completely disagree with the first one:</span><br></div></div></=
div><div><div style=3D"background-color:rgb(250,250,250);border:1px solid r=
gb(187,187,187)" class=3D"gmail-m_8379393266792367609prettyprint"><code cla=
ss=3D"gmail-m_8379393266792367609prettyprint"><div class=3D"gmail-m_8379393=
266792367609subprettyprint"><span style=3D"color:rgb(0,0,136)" class=3D"gma=
il-m_8379393266792367609styled-by-prettify">template</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"> <=
/span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_837939326679236=
7609styled-by-prettify"><</span><span style=3D"color:rgb(0,0,136)" class=
=3D"gmail-m_8379393266792367609styled-by-prettify">class</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettif=
y"> T</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_837939326=
6792367609styled-by-prettify">></span><span style=3D"color:rgb(0,0,0)" c=
lass=3D"gmail-m_8379393266792367609styled-by-prettify"><br></span><span sty=
le=3D"color:rgb(0,0,136)" class=3D"gmail-m_8379393266792367609styled-by-pre=
ttify">class</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_837939=
3266792367609styled-by-prettify"> </span><span style=3D"color:rgb(102,0,102=
)" class=3D"gmail-m_8379393266792367609styled-by-prettify">RedPtr</span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by=
-prettify"> </span><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_8379=
393266792367609styled-by-prettify">/* red like: super green */</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-pr=
ettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_83793=
93266792367609styled-by-prettify">{</span><span style=3D"color:rgb(0,0,0)" =
class=3D"gmail-m_8379393266792367609styled-by-prettify"><br>=C2=A0 </span><=
span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_8379393266792367609style=
d-by-prettify">private</span><span style=3D"color:rgb(102,102,0)" class=3D"=
gmail-m_8379393266792367609styled-by-prettify">:</span><span class=3D"gmail=
-"><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609sty=
led-by-prettify"><br>=C2=A0 =C2=A0 T</span><span style=3D"color:rgb(102,102=
,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">*</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-pr=
ettify"> m_ptr</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_=
8379393266792367609styled-by-prettify">;</span><span style=3D"color:rgb(0,0=
,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"><br>=C2=A0 </s=
pan><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_8379393266792367609=
styled-by-prettify">public</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_8379393266792367609styled-by-prettify">:</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-=
m_8379393266792367609styled-by-prettify">RedPtr</span><span style=3D"color:=
rgb(102,102,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">(</=
span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-m_8379393266792367=
609styled-by-prettify">RedPtr</span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"gmail-m_8379393266792367609styled-by-prettify">&&);</span><s=
pan style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,102,0)" c=
lass=3D"gmail-m_8379393266792367609styled-by-prettify">~</span><span style=
=3D"color:rgb(102,0,102)" class=3D"gmail-m_8379393266792367609styled-by-pre=
ttify">RedPtr</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_8=
379393266792367609styled-by-prettify">();</span></span><span style=3D"color=
:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"><br><b=
r>=C2=A0 =C2=A0</span><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_8=
379393266792367609styled-by-prettify">// void operator delocate() =3D defau=
lt; // autogenerated by the compiler</span><span style=3D"color:rgb(0,0,0)"=
class=3D"gmail-m_8379393266792367609styled-by-prettify"><br>=C2=A0 =C2=A0<=
/span><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_83793932667923676=
09styled-by-prettify">// void operator relocate() =3D default; // autogener=
ated by the compiler</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-=
m_8379393266792367609styled-by-prettify"><br></span><span style=3D"color:rg=
b(102,102,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">};</s=
pan><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609st=
yled-by-prettify"><br><br></span><span style=3D"color:rgb(0,0,136)" class=
=3D"gmail-m_8379393266792367609styled-by-prettify">static_assert</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-m_8379393266792367609styled=
-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_837=
9393266792367609styled-by-prettify">is_florian_<wbr>relocatable_v</span><sp=
an style=3D"color:rgb(102,102,0)" class=3D"gmail-m_8379393266792367609style=
d-by-prettify"><</span><span style=3D"color:rgb(102,0,102)" class=3D"gma=
il-m_8379393266792367609styled-by-prettify">RedPtr</span><span style=3D"col=
or:rgb(0,136,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">&l=
t;int></span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_83793=
93266792367609styled-by-prettify">>);</span><span style=3D"color:rgb(0,0=
,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"><br></span><sp=
an style=3D"color:rgb(0,0,136)" class=3D"gmail-m_8379393266792367609styled-=
by-prettify">static_assert</span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_8379393266792367609styled-by-prettify">(</span><span style=3D"c=
olor:rgb(0,0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">is=
_florian_<wbr>trivially_relocatable_v</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify"><</span><s=
pan style=3D"color:rgb(102,0,102)" class=3D"gmail-m_8379393266792367609styl=
ed-by-prettify">RedPtr</span><span style=3D"color:rgb(0,136,0)" class=3D"gm=
ail-m_8379393266792367609styled-by-prettify"><wbr><int></span><span s=
tyle=3D"color:rgb(102,102,0)" class=3D"gmail-m_8379393266792367609styled-by=
-prettify">>);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_8=
379393266792367609styled-by-prettify"> </span><span style=3D"color:rgb(136,=
0,0)" class=3D"gmail-m_8379393266792367609styled-by-prettify">// int* is tr=
ivially relocatable so behavior is "inherited"</span></div></code=
></div></div></div></blockquote><div><br></div><div>You are proposing that =
this type should be considered trivially fullrelocatable, even though the c=
ompiler has no idea what its move constructor and destructor do.</div><div>=
Please explain, in the form of a code sample, how you envision a library wo=
uld take advantage of the fullrelocation operation to speed up a common ope=
ration (such as std::vector::resize or std::swap =E2=80=94 but I'll acc=
ept different examples too). Remember, your library is not allowed to segfa=
ult when presented with std::list.</div><div><br></div><div><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-=
width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><div>Your code looks like an offset pointer wh=
ose range is limited. An offset pointer is a tricky question in general.<br=
></div></div></blockquote><div><br></div><div>Yes, it is. Does your propose=
d library segfault when presented with offset_ptr?=C2=A0 P1144 does not.</d=
iv><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:=
rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></div><div>So I wo=
uld say the NearPtr shouldn't relocatable to be safe</div></div></block=
quote><div><br></div><div>Please describe how your compiler would ensure th=
at NearPtr was <i>not</i> considered trivially fullrelocatable, <i>yet, at =
the same time</i>, ensure that RedPtr was considered trivially fullrelocata=
ble.</div><div><br></div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2BsDmOqNrV0GFdeDcoBVsz4%2BQD4=
xrAMxwuC%3Dc9AOn5Qtg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2Bs=
DmOqNrV0GFdeDcoBVsz4%2BQD4xrAMxwuC%3Dc9AOn5Qtg%40mail.gmail.com</a>.<br />
--000000000000cad19e057331b2d0--
.
Author: florian.csdt@gmail.com
Date: Sun, 12 Aug 2018 02:45:54 -0700 (PDT)
Raw View
------=_Part_1155_1027003799.1534067154725
Content-Type: multipart/alternative;
boundary="----=_Part_1156_1556936969.1534067154727"
------=_Part_1156_1556936969.1534067154727
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le dimanche 12 ao=C3=BBt 2018 02:02:55 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Sat, Aug 11, 2018 at 1:32 PM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>> Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit =
:
>>>
>>>
>>> Ah. If I understand correctly, this is merely an artifact of our=20
>>> different definitions of "relocate."
>>> For my P1144, "relocate =3D move + destroy," and therefore if you want =
to=20
>>> customize how your type is "relocated," you just give it a user-provide=
d=20
>>> move-constructor and/or a user-provided destructor =E2=80=94 the same t=
hing you=20
>>> already do today.
>>> For your scheme, as originally described, I said it was "relocate =3D=
=20
>>> memcpy + fixup." You have now changed it (good!) to what I would call=
=20
>>> "relocate =3D serialize + memcpy + deserialize." Now here's where we c=
rossed=20
>>> wires. In your old scheme, I was using the term "relocate" to mean the=
=20
>>> *entire* operation, but I now see that you were using the term=20
>>> "relocate" to mean *just the fixup half* of the operation. In your new=
=20
>>> scheme, I assume, you would use the term "relocate" to mean *just the=
=20
>>> deserialize part* of the operation.
>>> So I now agree, under your terminology, P1144 does not permit the user=
=20
>>> to define a "relocate" operation, because P1144 does not admit the=20
>>> existence of any such operation. P1144 doesn't have what I would call a=
=20
>>> "fixup" or "deserialize" step. It *only* has move plus destroy. You=20
>>> agree that these two operations are both customizable by the user; you =
just=20
>>> disagree that either of them, or the combination of both of them, shoul=
d be=20
>>> known by the word "relocate." I strongly disagree, of course. :)
>>>
>>
>> Wording is a tough topic. At the beginning, relocation meant the entire=
=20
>> process (but as it was a single step, that was fine). Then, I needed a a=
=20
>> second step before the other. And delocate was just the perfect name. Bu=
t=20
>> now, I don't have any word to mean the entire process... So for now let'=
s=20
>> stick to "full relocation".
>>
>> So full relocation =3D delocate + moving bytes around (optional) + reloc=
ate
>>
>
> Please find a verb that describes the entire process. In English (and=20
> standardese) you can't have the relationship
>
> $adverb $verb1 :=3D something + something + $verb1
>
> That is, "full relocation" must by definition be *a kind of*=20
> "relocation." (What kind of relocation? Full relocation.)
> You can't have "full relocation" meaning "relocation, but with two=20
> additional steps on the front that do not happen during any other kind of=
=20
> relocation."
>
Please try to be understanding on this subject: I'm not a native english=20
speaker, so what you find natural might not be for me.
Also, you might find names that I could not think of.
So any help on this subject is appreciated.
So let's stick to relocation meaing the whole process (this does not=20
include memcpy, though).
=20
>
> Compare: "Trivial relocation" means relocation that is trivial.
> "Nothrow relocation" means relocation that is nothrow.
> (And in my last response, "efficient relocation" meant "relocation that i=
s=20
> efficient.")
>
> So for this message (and this message only), I'll use the verb=20
> "fullrelocate" as meaning "delocate + memcpy + relocate", but I'm not goi=
ng=20
> to use that verb any more after that.
>
> I strongly, strongly suggest that you adopt the verb "relocate" as meanin=
g=20
> "deserialize + memcpy + serialize" (that is, replace your "operator=20
> relocate" with an "operator serialize"). That will bring your terminology=
=20
> into line with the terminology that has been established in previous=20
> discussions in this forum (by myself, Nicol, Niall, Facebook Folly, EASTL=
,=20
> etc.)
>
I'm not really happy with serialize/deserialize, as it is almost always=20
used for communication or storage. This is not what I'm proposing is about.=
=20
But I'm fine sticking to it until we find better names.
Please also note that serialization has the same defect as my previous=20
naming: the word "serialization" is sometime used to refer to the whole=20
process.
So for now, and until we find better names: relocate =3D serialize +=20
deserialize
=20
>
> [...]
>
>> Okay, agreed.
>>> Your old scheme defined "entireprocess =3D memcpy + relocate" (where I=
=20
>>> would say "relocate =3D memcpy + fixup"). So for me, "nothrow relocata=
ble"=20
>>> means "the entire process is nothrow", whereas for you, "nothrow=20
>>> relocatable" means "just the fixup step is nothrow."
>>>
>>
>> As delocate/relocate have no meaning on their own, when I say a type is=
=20
>> [trivially|nothrow] relocatable, I mean the entire process is=20
>> [trivially|nothrow] relocatable.
>>
>
> Again, that's not how English works. "Trivially relocatable" *by=20
> definition* means that the relocate operation, the relocation, is=20
> trivial. You are allowed to make up words, but you still have to put them=
=20
> together in the ways that have been established for communication over th=
e=20
> past ~2000 years.
>
> Also, it doesn't make any sense to say that a "process" is trivially=20
> relocatable. I infer that you meant to say *the entire process of=20
> fullrelocation is [trivial|nothrow]*.
> The way you'd express that concisely in English is "the type is=20
> [trivially|nothrow] fullrelocatable." This is why it's important to have=
a=20
> word for the entire process! (And we do: everyone but you calls the enti=
re=20
> process by the word "relocation.")
>
>
I agree. Also we still don't share the same definition of relocation even=
=20
when relocation refers to the entire process for me.
=20
>
> and it is also possible to have copyable movable types that are not=20
>>>> relocatable.
>>>>
>>>
>>> ...because you define "relocatable" to mean not just=20
>>> "gettable-from-point-A-to-point-B" but "gettable *by this specific=20
>>> mechanism* involving `operator relocate`."
>>>
>> So by your definition, IIUC, std::string would not be relocatable at=20
>>> all; boost::unique_ptr would not be relocatable at all; folly::FBVector=
=20
>>> would not be relocatable at all...
>>>
>>
>> Of course they would be. Why wouldn't they?
>> Those are just pointers, and pointers are trivially relocatable. So the=
=20
>> compiler generated operators delocate/relocate would also be trivially=
=20
>> relocatable.
>>
>
> Please explain how you propose to do this for boost::unique_ptr, without=
=20
> completely breaking std::list.
>
You do like for move semantic: you go the other way around by defining=20
explicitly operator serialize/deserialize for std::list.
template <class T>
class list {
private:
struct node {
node *previous, *next;
};
struct data_node : node {
T data;
};
=20
node sentinel;
public:
list() : sentinel{&sentinel, &sentinel} {}
list(const list&);
list(list&& other) : sentinel(other.empty() ? node{&sentinel, &sentinel=
}=20
: other.sentinel) {
other.sentinel.previous =3D &other.sentinel;
other.sentinel.next =3D &other.sentinel;
}
list& operator=3D(const list&);
list& operator=3D(list&&);
~list();
bool empty() const {
return sentinel.next =3D=3D &sentinel;
}
void operator serialize() {
if (empty()) {
sentinel.previous =3D nullptr;
sentinel.next =3D nullptr;
}
}
void operator deserialize() {
if (sentinel.next) { // list is not empty
sentinel.next->previous =3D &sentinel;
sentinel.previous->next =3D &sentinel;
} else {
sentinel.next =3D &sentinel;
sentinel.previous =3D &sentinel;
}
}
};
=20
> Appendix C of P1144=20
> <http://quuxplusone.github.io/draft/d1144-object-relocation.html#non-triv=
ial-samples>=20
> will be useful to you; it lists four situations that can make a type=20
> non-trivially relocatable.
>
I agree with those 4 cases. But the compiler cannot reliably detect those=
=20
(at least not in the general case). The most you could do is make this UB=
=20
(which is actually a good idea).
=20
>
>
> I agree with the two last versions (YellowPtr and GreenPtr), But I=20
>> completely disagree with the first one:
>> template <class T>
>> class RedPtr /* red like: super green */ {
>> private:
>> T* m_ptr;
>> public:
>> RedPtr(RedPtr&&);
>> ~RedPtr();
>>
>> // void operator delocate() =3D default; // autogenerated by the=20
>> compiler
>> // void operator relocate() =3D default; // autogenerated by the=20
>> compiler
>> };
>>
>> static_assert(is_florian_relocatable_v<RedPtr<int>>);
>> static_assert(is_florian_trivially_relocatable_v<RedPtr<int>>); // int*=
=20
>> is trivially relocatable so behavior is "inherited"
>>
>
> You are proposing that this type should be considered trivially=20
> fullrelocatable, even though the compiler has no idea what its move=20
> constructor and destructor do.
>
Yes. Most types use pointers either to allocate memory (and this memory is=
=20
not relocated when the object is), or to reference to preexisting objects=
=20
that will not be relocated at the same time as the first one.
Only in your 4 cases it will not work, but that's not for so many types. In=
=20
those cases, you would need to explicitly define/delete your=20
serialize/deserialize.
=20
> Please explain, in the form of a code sample, how you envision a library=
=20
> would take advantage of the fullrelocation operation to speed up a common=
=20
> operation (such as std::vector::resize or std::swap =E2=80=94 but I'll ac=
cept=20
> different examples too). Remember, your library is not allowed to segfaul=
t=20
> when presented with std::list.
>
>
Here is swap.
std::list will not segfault because we defined operator=20
serialize/deserialize for it (see above).
template <class T>
void swap(T& a, T& b) {
if constexpr (is_nothrow_relocatable_v<T>) {
a.serialize();
b.serialize();
byte pa =3D reinterpret_cast<byte*>(&a);
byte pb =3D reinterpret_cast<byte*>(&b);
=20
swap_ranges(pa, pa+sizeof(T), pb);
a.deserialize();
b.deserialize();
} else {
T c =3D std::move(a);
a =3D std::move(b);
b =3D std::move(c);
}
}
=20
>
> Your code looks like an offset pointer whose range is limited. An offset=
=20
>> pointer is a tricky question in general.
>>
>
> Yes, it is. Does your proposed library segfault when presented with=20
> offset_ptr? P1144 does not.
>
>
If offset_ptr is made non-relocatable, then my proposed library will not=20
segfault as it will fallback to move.
If offset_ptr is kept implicitly relocatable, then it will depend on how it=
=20
will be used.
For instance, we can teach people to pointers to point outside the object=
=20
and offset_ptr to point within the object. Their types will then be safely=
=20
relocatables.
And if they need a pointer to point within the object or an offset_ptr to=
=20
point outside the object, then they would need to define/delete relocation.
The former is safer, while the latter would lead to more effeicient code,=
=20
but also more efforts.
=20
> So I would say the NearPtr shouldn't relocatable to be safe
>>
>
> Please describe how your compiler would ensure that NearPtr was *not*=20
> considered trivially fullrelocatable, *yet, at the same time*, ensure=20
> that RedPtr was considered trivially fullrelocatable.
>
> =E2=80=93Arthur
>
struct NearPtr {
/* ... */
void operator serialize() =3D delete;
};
The main problem you are trying to highlight with my design is: either=20
almost no types would be made implicitly relocatable, or we will have=20
false-positive.
While I agree with this concern, I also want to point that your design has=
=20
the same defect to a certain extent.
The 4 cases you expressed are great, but are not bound to a type in the=20
general case (it cannot be detected reliably by the compiler). We could=20
make it UB, but we cannot go further than that.
What we can do is tweaking the implicit generation of serialize/deserialize=
=20
depending on the copy/move behaviour of the object.
Exactly like what has been done when introducing move semantics.
If copy/move are defaulted, implicitly generating serialize/deserialize is=
=20
fine.
If copy/move are defined but not defaulted, it is arguable, but I think=20
implicitly generating serailize/deserialize is also fine (std::vector for=
=20
instance).
If copy is deleted, I'm not sure...
If copy and move are deleted, the safest would be to not generate=20
serialize/deserialize
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/05cd596d-8582-4a0c-8f04-e0e3eef0d9b0%40isocpp.or=
g.
------=_Part_1156_1556936969.1534067154727
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le dimanche 12 ao=C3=BBt 2018 02:02:55 UTC+2, Arth=
ur O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr">On Sat, Aug 11, 2018 at 1:32 PM, <span dir=3D"ltr">=
<<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"v-4b=
-UqxDQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:'=
;return true;" onclick=3D"this.href=3D'javascript:';return true;">f=
loria...@gmail.com</a>></span> wrote:<br><div><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);=
padding-left:1ex"><div dir=3D"ltr">Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC=
+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote class=3D"gmail_=
quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-=
style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>Ah. If I under=
stand correctly, this is merely an artifact of our different definitions of=
"relocate."</div><div>For my P1144, "relocate =3D move + de=
stroy," and therefore if you want to customize how your type is "=
relocated," you just give it a user-provided move-constructor and/or a=
user-provided destructor =E2=80=94 the same thing you already do today.</d=
iv><div>For your scheme, as originally described, I said it was "reloc=
ate =3D memcpy + fixup." =C2=A0You have now changed it (good!) to what=
I would call "relocate =3D serialize + memcpy + deserialize." =
=C2=A0Now here's where we crossed wires.=C2=A0 In your old scheme, I wa=
s using the term "relocate" to mean the <i>entire</i> operation, =
but I now see that you were using the term "relocate" to mean <i>=
just the fixup half</i> of the operation.=C2=A0 In your new scheme, I assum=
e, you would use the term "relocate" to mean <i>just the deserial=
ize part</i> of the operation.</div><div>So I now agree, under your termino=
logy, P1144 does not permit the user to define a "relocate" opera=
tion, because P1144 does not admit the existence of any such operation. P11=
44 doesn't have what I would call a "fixup" or "deserial=
ize" step. It <i>only</i> has move plus destroy. You agree that these =
two operations are both customizable by the user; you just disagree that ei=
ther of them, or the combination of both of them, should be known by the wo=
rd "relocate." =C2=A0I strongly disagree, of course. :)</div></di=
v></div></div></blockquote><div><br></div></span><div>Wording is a tough to=
pic. At the beginning, relocation meant the entire process (but as it was a=
single step, that was fine). Then, I needed a a second step before the oth=
er. And delocate was just the perfect name. But now, I don't have any w=
ord to mean the entire process... So for now let's stick to "full =
relocation".</div><div><br></div><div>So full relocation =3D delocate =
+ moving bytes around (optional) + relocate<br></div></div></blockquote><di=
v><br></div><div>Please find a verb that describes the entire process. In E=
nglish (and standardese) you can't have the relationship</div><div><br>=
</div><div>=C2=A0 =C2=A0 $adverb $verb1 :=3D something + something + $verb1=
</div><div><br></div><div>That is, "full relocation" must by defi=
nition be <i>a kind of</i> "relocation." (What kind of relocation=
? Full relocation.)</div><div>You can't have "full relocation"=
; meaning "relocation, but with two additional steps on the front that=
do not happen during any other kind of relocation."</div></div></div>=
</div></blockquote><div><br></div><div>Please try to be understanding on th=
is subject: I'm not a native english speaker, so what you find natural =
might not be for me.</div><div>Also, you might find names that I could not =
think of.</div><div>So any help on this subject is appreciated.</div><div><=
br></div><div>So let's stick to relocation meaing the whole process (th=
is does not include memcpy, though).<br></div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_=
quote"><div><br></div><div>Compare: "Trivial relocation" means re=
location that is trivial.</div><div>"Nothrow relocation" means re=
location that is nothrow.</div><div>(And in my last response, "efficie=
nt relocation" meant "relocation that is efficient.")</div><=
div><br></div><div>So for this message (and this message only), I'll us=
e the verb "fullrelocate" as meaning "delocate + memcpy + re=
locate", but I'm not going to use that verb any more after that.</=
div><div><br></div><div>I strongly, strongly suggest that you adopt the ver=
b "relocate" as meaning "deserialize + memcpy + serialize&qu=
ot; (that is, replace your "operator relocate" with an "oper=
ator serialize"). That will bring your terminology into line with the =
terminology that has been established in previous discussions in this forum=
(by myself, Nicol, Niall, Facebook Folly, EASTL, etc.)</div></div></div></=
div></blockquote><br>I'm not really happy with serialize/deserialize, a=
s it is almost always used for communication or storage. This is not what I=
'm proposing is about. But I'm fine sticking to it until we find be=
tter names.<br>Please also note that serialization has the same defect as m=
y previous naming: the word "serialization" is sometime used to r=
efer to the whole process.<br><br>So for now, and until we find better name=
s: relocate =3D serialize + deserialize<br><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quo=
te"><div><br></div><div>[...]</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);=
padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div>Okay, ag=
reed.<br></div><div>Your old scheme defined "entireprocess =3D memcpy =
+ relocate" (where I would say "relocate =3D memcpy + fixup"=
).=C2=A0 So for me, "nothrow relocatable" means "the entire =
process is nothrow", whereas for you, "nothrow relocatable" =
means "just the fixup step is nothrow."</div></div></div></blockq=
uote><div><br></div></span><div>As delocate/relocate have no meaning on the=
ir own, when I say a type is [trivially|nothrow] relocatable, I mean the en=
tire process is [trivially|nothrow] relocatable.</div></div></blockquote><d=
iv><br></div><div>Again, that's not how English works. "Trivially =
relocatable" <i>by definition</i> means that the relocate operation, t=
he relocation, is trivial. You are allowed to make up words, but you still =
have to put them together in the ways that have been established for commun=
ication over the past ~2000 years.</div><div><br></div><div>Also, it doesn&=
#39;t make any sense to say that a "process" is trivially relocat=
able.=C2=A0 I infer that you meant to say <i>the entire process of fullrelo=
cation is [trivial|nothrow]</i>.</div><div>The way you'd express that c=
oncisely in English is "the type is [trivially|nothrow] fullrelocatabl=
e." =C2=A0This is why it's important to have a word for the entire=
process! =C2=A0(And we do: everyone but you calls the entire process by th=
e word "relocation.")</div><div><br></div></div></div></div></blo=
ckquote><div><br></div><div>I agree. Also we still don't share the same=
definition of relocation even when relocation refers to the entire process=
for me.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-st=
yle:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"=
ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid=
;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div=
> and it is also possible to have copyable movable types that are not reloc=
atable.</div></div></blockquote><div><br></div><div>...because you define &=
quot;relocatable" to mean not just "gettable-from-point-A-to-<wbr=
>point-B" but "gettable <i>by this specific mechanism</i> involvi=
ng `operator relocate`."</div></div></div></div></blockquote></span><s=
pan><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,20=
4);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=
=C2=A0So by your definition, IIUC, std::string would not be relocatable at =
all; boost::unique_ptr would not be relocatable at all; folly::FBVector wou=
ld not be relocatable at all...</div></div></div></div></blockquote><div><b=
r></div></span><div>Of course they would be. Why wouldn't they?</div><d=
iv>Those are just pointers, and pointers are trivially relocatable. So the =
compiler generated operators delocate/relocate would also be trivially relo=
catable.</div></div></blockquote><div><br></div><div>Please explain how you=
propose to do this for boost::unique_ptr, without completely breaking std:=
:list.</div></div></div></div></blockquote><div><br></div><div>You do like =
for move semantic: you go the other way around by defining explicitly opera=
tor serialize/deserialize for std::list.</div><div><div style=3D"background=
-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style:=
solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint=
"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"=
color: #008;" class=3D"styled-by-prettify">template</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>class</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> lis=
t </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">private</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> node </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 node </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">previous</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">*</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">next</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> data_node </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> node </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 T data</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 node sentinel</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">public</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 list</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> sentinel</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>sentinel</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 list</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> list</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 list</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">list</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&&</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> other</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> sentinel</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">other</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">empty</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">?</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> node</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{&a=
mp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sentine=
l</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">sentinel</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> other</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">sentinel</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 ot=
her</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">previous </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">other</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">sentinel</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 =C2=A0 =C2=A0 other</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">sentinel</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>next</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">other</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">sentinel</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 list</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">operator</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D(</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> list</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&am=
p;);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 list</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">operat=
or</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">list</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&&);</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">~</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">list</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> empty</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> sentinel</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">next</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> serialize</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">if</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
empty</span><span style=3D"color: #660;" class=3D"styled-by-prettify">())</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 sentinel</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">previou=
s </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">nullptr</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 sent=
inel</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">next</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">nullptr</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">operator</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> deserialize</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">next</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// list is not empty</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 sentinel</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">next</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">-></span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">previous </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">sentinel</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 sentinel</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">previous</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">-></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">next</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">else</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 sentinel</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">next</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sent=
inel</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 sentinel</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">previous </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">sentinel</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br><=
br></div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><a href=3D=
"http://quuxplusone.github.io/draft/d1144-object-relocation.html#non-trivia=
l-samples" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D&#=
39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxplusone.github.io%2Fdraf=
t%2Fd1144-object-relocation.html%23non-trivial-samples\x26sa\x3dD\x26sntz\x=
3d1\x26usg\x3dAFQjCNHGMNg6-Yx1BjiEE1MetwX2kUWFPA';return true;" onclick=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxpluson=
e.github.io%2Fdraft%2Fd1144-object-relocation.html%23non-trivial-samples\x2=
6sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHGMNg6-Yx1BjiEE1MetwX2kUWFPA';ret=
urn true;">Appendix C of P1144</a> will be useful to you; it lists four sit=
uations that can make a type non-trivially relocatable.</div></div></div></=
div></blockquote><div><br></div><div>I agree with those 4 cases. But the co=
mpiler cannot reliably detect those (at least not in the general case). The=
most you could do is make this UB (which is actually a good idea).<br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div><div class=3D"gmail_quote"><div><br></div><div><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-=
left:1ex"><div dir=3D"ltr"><div><div><div><span style=3D"color:rgb(34,34,34=
)">I agree with the two last versions (YellowPtr and GreenPtr), But I compl=
etely disagree with the first one:</span><br></div></div></div><div><div st=
yle=3D"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187)"=
><code><div><span style=3D"color:rgb(0,0,136)">template</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</sp=
an><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(=
0,0,0)"> T</span><span style=3D"color:rgb(102,102,0)">></span><span styl=
e=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">class<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102=
,0,102)">RedPtr</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(136,0,0)">/* red like: super green */</span><span style=3D"co=
lor:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span =
style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,1=
36)">private</span><span style=3D"color:rgb(102,102,0)">:</span><span><span=
style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 T</span><span style=3D"color:=
rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)"> m_ptr</span><span=
style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><b=
r>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">public</span><span style=
=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:rgb(102,0,102)">RedPtr</span><span s=
tyle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,102)">=
RedPtr</span><span style=3D"color:rgb(102,102,0)">&&);</span><span =
style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rg=
b(102,102,0)">~</span><span style=3D"color:rgb(102,0,102)">RedPtr</span><sp=
an style=3D"color:rgb(102,102,0)">();</span></span><span style=3D"color:rgb=
(0,0,0)"><br><br>=C2=A0 =C2=A0</span><span style=3D"color:rgb(136,0,0)">// =
void operator delocate() =3D default; // autogenerated by the compiler</spa=
n><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0</span><span style=3D"c=
olor:rgb(136,0,0)">// void operator relocate() =3D default; // autogenerate=
d by the compiler</span><span style=3D"color:rgb(0,0,0)"><br></span><span s=
tyle=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br=
><br></span><span style=3D"color:rgb(0,0,136)">static_assert</span><span st=
yle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">is_fl=
orian_<wbr>relocatable_v</span><span style=3D"color:rgb(102,102,0)"><</s=
pan><span style=3D"color:rgb(102,0,102)">RedPtr</span><span style=3D"color:=
rgb(0,136,0)"><int></span><span style=3D"color:rgb(102,102,0)">>);=
</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb=
(0,0,136)">static_assert</span><span style=3D"color:rgb(102,102,0)">(</span=
><span style=3D"color:rgb(0,0,0)">is_florian_<wbr>trivially_relocatable_v</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(102,0,102)">RedPtr</span><span style=3D"color:rgb(0,136,0)"><wbr><int=
></span><span style=3D"color:rgb(102,102,0)">>);</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">// int* is tr=
ivially relocatable so behavior is "inherited"</span></div></code=
></div></div></div></blockquote><div><br></div><div>You are proposing that =
this type should be considered trivially fullrelocatable, even though the c=
ompiler has no idea what its move constructor and destructor do.</div></div=
></div></div></blockquote><div><br></div><div>Yes. Most types use pointers =
either to allocate memory (and this memory is not relocated when the object=
is), or to reference to preexisting objects that will not be relocated at =
the same time as the first one.</div><div>Only in your 4 cases it will not =
work, but that's not for so many types. In those cases, you would need =
to explicitly define/delete your serialize/deserialize.<br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
><div class=3D"gmail_quote"><div>Please explain, in the form of a code samp=
le, how you envision a library would take advantage of the fullrelocation o=
peration to speed up a common operation (such as std::vector::resize or std=
::swap =E2=80=94 but I'll accept different examples too). Remember, you=
r library is not allowed to segfault when presented with std::list.</div><d=
iv><br></div></div></div></div></blockquote><div><br></div><div>Here is swa=
p.</div><div>std::list will not segfault because we defined operator serial=
ize/deserialize for it (see above).<br></div><div><div style=3D"background-=
color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: =
solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> swap<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">is_nothrow_relocatable_v</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">>)</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 a</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">seri=
alize</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">serialize</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">byte</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> pa </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">byte</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">*>(&</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">a</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">byte</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> pb </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">r=
einterpret_cast</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">b=
yte</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*>(&=
amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">b</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 <br>=
=C2=A0 =C2=A0 swap_ranges</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">pa</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> pa</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">+</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">),</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> pb</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br><br>=C2=A0 =C2=A0 a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">deserialize</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 =C2=A0 b</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>deserialize</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">else</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 T c </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">move</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 a </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">move</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">b</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 b </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">move</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">c<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span></div></code></div><br><br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div><div class=3D"gmail_quote"><div></div><div><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div>Your code looks like an offset pointer whose ra=
nge is limited. An offset pointer is a tricky question in general.<br></div=
></div></blockquote><div><br></div><div>Yes, it is. Does your proposed libr=
ary segfault when presented with offset_ptr?=C2=A0 P1144 does not.</div><di=
v><br></div></div></div></div></blockquote><div><br></div><div>If offset_pt=
r is made non-relocatable, then my proposed library will not segfault as it=
will fallback to move.</div><div><br></div><div>If offset_ptr is kept impl=
icitly relocatable, then it will depend on how it will be used.</div><div>F=
or instance, we can teach people to pointers to point outside the object an=
d offset_ptr to point within the object. Their types will then be safely re=
locatables.</div><div>And if they need a pointer to point within the object=
or an offset_ptr to point outside the object, then they would need to defi=
ne/delete relocation.</div><div><br></div><div>The former is safer, while t=
he latter would lead to more effeicient code, but also more efforts.<br></d=
iv><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><div></div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"ltr"><div></div><div>So I would say the NearPtr shouldn't relocat=
able to be safe</div></div></blockquote><div><br></div><div>Please describe=
how your compiler would ensure that NearPtr was <i>not</i> considered triv=
ially fullrelocatable, <i>yet, at the same time</i>, ensure that RedPtr was=
considered trivially fullrelocatable.</div><div><br></div><div>=E2=80=93Ar=
thur</div></div></div></div></blockquote><div><br></div><div><div style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"p=
rettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">NearPtr</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">/* ... */</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">operator</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> serialize</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">delete</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span></div></code></div></div><div><br></div><div=
><br>The main problem you are trying to highlight with my design is: either=
almost no types would be made implicitly relocatable, or we will have fals=
e-positive.</div><div>While I agree with this concern, I also want to point=
that your design has the same defect to a certain extent.<br></div><div>Th=
e 4 cases you expressed are great, but are not bound to a type in the gener=
al case (it cannot be detected reliably by the compiler). We could make it =
UB, but we cannot go further than that.</div><div><br></div><div>What we ca=
n do is tweaking the implicit generation of serialize/deserialize depending=
on the copy/move behaviour of the object.</div><div>Exactly like what has =
been done when introducing move semantics.</div><div><br></div><div>If copy=
/move are defaulted, implicitly generating serialize/deserialize is fine.</=
div><div>If copy/move are defined but not defaulted, it is arguable, but I =
think implicitly generating serailize/deserialize is also fine (std::vector=
=C2=A0 for instance).</div><div>If copy is deleted, I'm not sure...</di=
v><div>If copy and move are deleted, the safest would be to not generate se=
rialize/deserialize<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/05cd596d-8582-4a0c-8f04-e0e3eef0d9b0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/05cd596d-8582-4a0c-8f04-e0e3eef0d9b0=
%40isocpp.org</a>.<br />
------=_Part_1156_1556936969.1534067154727--
------=_Part_1155_1027003799.1534067154725--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sun, 12 Aug 2018 16:32:45 -0700
Raw View
--000000000000e96fd605734564c5
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sun, Aug 12, 2018 at 2:45 AM, <florian.csdt@gmail.com> wrote:
> Le dimanche 12 ao=C3=BBt 2018 02:02:55 UTC+2, Arthur O'Dwyer a =C3=A9crit=
:
>>
>> On Sat, Aug 11, 2018 at 1:32 PM, <floria...@gmail.com> wrote:
>>
>>> Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit=
:
>>>>
>>>>
>>>>
>>>>
>> I strongly, strongly suggest that you adopt the verb "relocate" as
>> meaning "deserialize + memcpy + serialize" (that is, replace your "opera=
tor
>> relocate" with an "operator serialize"). That will bring your terminolog=
y
>> into line with the terminology that has been established in previous
>> discussions in this forum (by myself, Nicol, Niall, Facebook Folly, EAST=
L,
>> etc.)
>>
>
> I'm not really happy with serialize/deserialize, as it is almost always
> used for communication or storage. This is not what I'm proposing is abou=
t.
> But I'm fine sticking to it until we find better names.
> Please also note that serialization has the same defect as my previous
> naming: the word "serialization" is sometime used to refer to the whole
> process.
>
> So for now, and until we find better names: relocate =3D serialize +
> deserialize
>
Okay. (Well, almost. We'll cover that below.)
and it is also possible to have copyable movable types that are not
>>>>> relocatable.
>>>>>
>>>>
>>>> ...because you define "relocatable" to mean not just
>>>> "gettable-from-point-A-to-point-B" but "gettable *by this specific
>>>> mechanism* involving `operator relocate`."
>>>>
>>> So by your definition, IIUC, std::string would not be relocatable at
>>>> all; boost::unique_ptr would not be relocatable at all; folly::FBVecto=
r
>>>> would not be relocatable at all...
>>>>
>>>
>>> Of course they would be. Why wouldn't they?
>>> Those are just pointers, and pointers are trivially relocatable. So the
>>> compiler generated operators delocate/relocate would also be trivially
>>> relocatable.
>>>
>>
>> Please explain how you propose to do this for boost::unique_ptr, without
>> completely breaking std::list.
>>
>
> You do like for move semantic: you go the other way around by defining
> explicitly operator serialize/deserialize for std::list.
>
(snip: an example implementation of std::list with a user-provided move
constructor, a user-provided destructor, a user-provided operator delocate,
and a user-provided operator relocate)
Okay, so that would be how you'd *enable* "relocation support" for
std::list.
And if you *didn't* provide any operator delocate or operator relocate for
std::list, then std::list would not be relocatable at all, is that right?
Well, boost::unique_ptr has a user-provided move constructor, a
user-provided destructor, and no operator delocate or operator relocate.
Therefore, by your logic, boost::unique_ptr would not be relocatable at
all, is that right?
> Appendix C of P1144
>> <http://quuxplusone.github.io/draft/d1144-object-relocation.html#non-tri=
vial-samples>
>> will be useful to you; it lists four situations that can make a type
>> non-trivially relocatable.
>>
>
> I agree with those 4 cases. But the compiler cannot reliably detect those
> (at least not in the general case). The most you could do is make this UB
> (which is actually a good idea).
>
Well, P1144 does better than "make this UB." P1144 actually supports the
generic algorithms vector::resize, std::swap, and
std::uninitialized_relocate for *all* move-constructible, destructible
types. These algorithms get compiled into memcpy exactly when it's safe to
do so (by observing the "trivially relocatable" concept), and fall back
onto "relocate =3D move + destroy" in the general case.
Please, please, open up Compiler Explorer and play around with it a little
bit!
(By P1144's definition, boost::unique_ptr is relocatable but not trivially
relocatable. You can observe this directly on CE.
<https://godbolt.org/g/nHC8GG>)
Please explain, in the form of a code sample, how you envision a library
>> would take advantage of the fullrelocation operation to speed up a commo=
n
>> operation (such as std::vector::resize or std::swap =E2=80=94 but I'll a=
ccept
>> different examples too). Remember, your library is not allowed to segfau=
lt
>> when presented with std::list.
>>
>
> Here is swap.
> std::list will not segfault because we defined operator
> serialize/deserialize for it (see above).
>
Okay, okay. boost::container::list, then. Let's play fair. :)
However, I already see from the code that for boost::container::list,
you'll just fall back onto move+destroy (the `else` block). So that's fine
=E2=80=94 no segfault, agreed. :)
> template <class T>
> void swap(T& a, T& b) {
> if constexpr (is_nothrow_relocatable_v<T>) {
> a.serialize();
> b.serialize();
>
> byte pa =3D reinterpret_cast<byte*>(&a);
> byte pb =3D reinterpret_cast<byte*>(&b);
>
> swap_ranges(pa, pa+sizeof(T), pb);
>
> a.deserialize();
> b.deserialize();
> } else {
> T c =3D std::move(a);
> a =3D std::move(b);
> b =3D std::move(c);
> }
> }
>
Here's P1144's std::swap, for comparison. (Please excuse the
libc++-uglification.)
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if<
is_move_constructible<_Tp>::value &&
is_move_assignable<_Tp>::value
>::type
swap(_Tp& __x, _Tp& __y)
_NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value &&
is_nothrow_move_assignable<_Tp>::value)
{
if (is_trivially_relocatable<_Tp>::value && !is_volatile<_Tp>::value) {
if (!is_empty<_Tp>::value) {
// TODO: if either __x or __y is a "possibly overlapping
subobject"
// in Itanium ABI terms, this will memcpy too much data. But th=
e
// same caveat has applied to std::copy and friends, since
forever.
char __t[sizeof (_Tp)];
_VSTD::memcpy(__t, _VSTD::addressof(__x), sizeof(_Tp));
_VSTD::memcpy(_VSTD::addressof(__x), _VSTD::addressof(__y),
sizeof(_Tp));
_VSTD::memcpy(_VSTD::addressof(__y), __t, sizeof(_Tp));
}
} else {
_Tp __t(_VSTD::move(__x));
__x =3D _VSTD::move(__y);
__y =3D _VSTD::move(__t);
}
}
Using std::swap_ranges is a neat trick I hadn't thought of; but FWIW, it
doesn't generate quite as nice codegen <https://godbolt.org/g/z5kcUY> as
the simple memcpy AFAICT.
>> Your code looks like an offset pointer whose range is limited. An offset
>>> pointer is a tricky question in general.
>>>
>>
>> Yes, it is. Does your proposed library segfault when presented with
>> offset_ptr? P1144 does not.
>>
>>
> If offset_ptr is made non-relocatable, then my proposed library will not
> segfault as it will fallback to move.
>
Right. So you're defining essentially two routes the user might take here:
relocate =3D serialize + memcpy + deserialize
relocate =3D move + destroy
If the user takes the first route by providing `operator delocate` and
`operator relocate`, then your `swap` will use those functions (which may
or may not be trivial) bracketing a simple memcpy.
If the user takes the second route by providing a trivial move-constructor
and a trivial destructor, then your `swap` doesn't-currently,-but-should
use a simple memcpy.
[...Switching gears now to talk about "position-independence"...]
> If offset_ptr is kept implicitly relocatable, then it will depend on how
> it will be used.
> For instance, we can teach people to pointers to point outside the object
> and offset_ptr to point within the object. Their types will then be safel=
y
> relocatables.
> And if they need a pointer to point within the object or an offset_ptr to
> point outside the object, then they would need to define/delete relocatio=
n.
>
Right, that's what makes "position-independence" such a harder problem. The
correct semantics for your `operator relocate` depend on how the user
is *intending
to use* the offset_ptr object in question. Some of the offset_ptrs in
their program (the ones used inside position-independent memory segments)
will be okay with an =3Ddefault'ed `operator relocate`, but others (the one=
s
used outside) will require `operator relocate` to do some fixup. This
would work great if we could somehow attach an `operator relocate`
implementation to an object at runtime based on how it's being used; but in
C++ we have to define `operator relocate`* for the entire type at once*.
And that's a problem, because there is no `operator relocate` that works
for the entire type =E2=80=94 at least, not as long as you're trying to fit
relocation and position-independence into the same box.
As soon as you split up relocation (an operation that can be defined
unambiguously at the type level) from position-independence (an operation
that nobody knows how to define, yet, except that it's certainly not a
property of a *type* in isolation), a good chunk of these problems go away.
So I would say the NearPtr shouldn't relocatable to be safe
>>>
>>
>> Please describe how your compiler would ensure that NearPtr was *not*
>> considered trivially fullrelocatable, *yet, at the same time*, ensure
>> that RedPtr was considered trivially fullrelocatable.
>>
>
> struct NearPtr {
> /* ... */
> void operator serialize() =3D delete;
> };
>
Unfortunately, this requires a change to the codebase of NearPtr, based on
human input. Some human being has to look at "NearPtr.h", realize that it
would invoke UB when compiled with a C++2a compiler, and add the `=3Ddelete=
`
line =E2=80=94 under an #ifdef of course, since that line wouldn't compile =
as C++17!
But the #ifdef is a minor concern compared to the human being's
involvement. You're basically proposing that in order to upgrade our
compiler from C++17 to C++2a, we have to pay a (fairly expert) software
engineer to comb over all of our header files looking for types that might
not be trivially serializable, and add this line to any of them they find.
That's a major code audit that could quite honestly take *months*, which is
to say, tens of thousands of dollars.
You see the problem, right?
The main problem you are trying to highlight with my design is: either
> almost no types would be made implicitly relocatable, or we will have
> false-positive.
> While I agree with this concern, I also want to point that your design ha=
s
> the same defect to a certain extent.
> The 4 cases you expressed are great, but are not bound to a type in the
> general case (it cannot be detected reliably by the compiler).
>
Yes it can. :) I dare you to find any C++17 code, anywhere in the world,
or even made up ad-hoc just for this purpose, which is mishandled by the
P1144 compiler on Godbolt.org. <https://godbolt.org/g/oYyHkg>
If you =E2=80=94 or anyone =E2=80=94 find any such code, please email me of=
f-list to
collect a bug bounty. :)
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0%2B_9AVCHpBw8ixf82uSoTz4g0b_0znNesFC%3DE_=
gnULJDA%40mail.gmail.com.
--000000000000e96fd605734564c5
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sun, Aug 12, 2018 at 2:45 AM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<div class=3D"gmail_extra"><div class=3D"gmail_q=
uote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr">Le dimanche 12 ao=C3=BBt 2018 02:02=
:55 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span class=3D"gmail-"><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padd=
ing-left:1ex"><div dir=3D"ltr">On Sat, Aug 11, 2018 at 1:32 PM, <span dir=
=3D"ltr"><<a rel=3D"nofollow">floria...@gmail.com</a>></span> wrote:<=
br><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Le sa=
medi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=
=A0:<span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"=
><div><br></div><div><br></div></div></div></div></blockquote></span></div>=
</blockquote></div></div></div></blockquote></span><span class=3D"gmail-"><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pa=
dding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br><=
/div><div>I strongly, strongly suggest that you adopt the verb "reloca=
te" as meaning "deserialize + memcpy + serialize" (that is, =
replace your "operator relocate" with an "operator serialize=
"). That will bring your terminology into line with the terminology th=
at has been established in previous discussions in this forum (by myself, N=
icol, Niall, Facebook Folly, EASTL, etc.)</div></div></div></div></blockquo=
te><br></span>I'm not really happy with serialize/deserialize, as it is=
almost always used for communication or storage. This is not what I'm =
proposing is about. But I'm fine sticking to it until we find better na=
mes.<br>Please also note that serialization has the same defect as my previ=
ous naming: the word "serialization" is sometime used to refer to=
the whole process.<br><br>So for now, and until we find better names: relo=
cate =3D serialize + deserialize</div></blockquote><div><br></div><div>Okay=
.. (Well, almost. We'll cover that below.)</div><div><br></div><div><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border=
-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div=
dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color=
:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr"><div> and it is also possible t=
o have copyable movable types that are not relocatable.</div></div></blockq=
uote><div><br></div><div>...because you define "relocatable" to m=
ean not just "gettable-from-point-A-to-poin<wbr>t-B" but "ge=
ttable <i>by this specific mechanism</i> involving `operator relocate`.&quo=
t;</div></div></div></div></blockquote></span><span><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div>=C2=A0So by your definition=
, IIUC, std::string would not be relocatable at all; boost::unique_ptr woul=
d not be relocatable at all; folly::FBVector would not be relocatable at al=
l...</div></div></div></div></blockquote><div><br></div></span><div>Of cour=
se they would be. Why wouldn't they?</div><div>Those are just pointers,=
and pointers are trivially relocatable. So the compiler generated operator=
s delocate/relocate would also be trivially relocatable.</div></div></block=
quote><div><br></div><div>Please explain how you propose to do this for boo=
st::unique_ptr, without completely breaking std::list.</div></div></div></d=
iv></blockquote><div><br></div></span><div>You do like for move semantic: y=
ou go the other way around by defining explicitly operator serialize/deseri=
alize for std::list.</div></div></blockquote><div><br></div><div>(snip: an =
example implementation of std::list with a user-provided move constructor, =
a user-provided destructor, a user-provided operator delocate, and a user-p=
rovided operator relocate)</div><div><br></div><div>Okay, so that would be =
how you'd <i>enable</i> "relocation support" for std::list.</=
div><div><br></div><div>And if you <i>didn't</i> provide any operator d=
elocate or operator relocate for std::list, then std::list would not be rel=
ocatable at all, is that right?</div><div><br></div><div>Well, boost::uniqu=
e_ptr has a user-provided move constructor, a user-provided destructor, and=
no operator delocate or operator relocate.</div><div>Therefore, by your lo=
gic, boost::unique_ptr would not be relocatable at all, is that right?</div=
><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bor=
der-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span cl=
ass=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb=
(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_q=
uote"><div><a href=3D"http://quuxplusone.github.io/draft/d1144-object-reloc=
ation.html#non-trivial-samples" rel=3D"nofollow" target=3D"_blank">Appendix=
C of P1144</a> will be useful to you; it lists four situations that can ma=
ke a type non-trivially relocatable.</div></div></div></div></blockquote><d=
iv><br></div></span><div>I agree with those 4 cases. But the compiler canno=
t reliably detect those (at least not in the general case). The most you co=
uld do is make this UB (which is actually a good idea).<br></div></div></bl=
ockquote><div><br></div><div>Well, P1144 does better than "make this U=
B." =C2=A0P1144 actually supports the generic algorithms vector::resiz=
e, std::swap, and std::uninitialized_relocate for <i>all</i> move-construct=
ible, destructible types. These algorithms get compiled into memcpy exactly=
when it's safe to do so (by observing the "trivially relocatable&=
quot; concept), and fall back onto "relocate =3D move + destroy" =
in the general case.</div><div>Please, please, open up Compiler Explorer an=
d play around with it a little bit!</div><div>(By P1144's definition, b=
oost::unique_ptr is relocatable but not trivially relocatable. <a href=3D"h=
ttps://godbolt.org/g/nHC8GG">You can observe this directly on CE.</a>)</div=
><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;borde=
r-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span clas=
s=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quo=
te"><div>Please explain, in the form of a code sample, how you envision a l=
ibrary would take advantage of the fullrelocation operation to speed up a c=
ommon operation (such as std::vector::resize or std::swap =E2=80=94 but I&#=
39;ll accept different examples too). Remember, your library is not allowed=
to segfault when presented with std::list.</div></div></div></div></blockq=
uote><div><br></div></span><div>Here is swap.</div><div>std::list will not =
segfault because we defined operator serialize/deserialize for it (see abov=
e).<br></div></div></blockquote><div><br></div><div>Okay, okay. boost::cont=
ainer::list, then.=C2=A0 Let's play fair. :)</div><div>However, I alrea=
dy see from the code that for boost::container::list, you'll just fall =
back onto move+destroy (the `else` block). So that's fine =E2=80=94 no =
segfault, agreed. :)</div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style=
:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div></div><div><div style=3D"background-color:rgb(250,250,250);border:1p=
x solid rgb(187,187,187)" class=3D"gmail-m_-7912082650157566418prettyprint"=
><code class=3D"gmail-m_-7912082650157566418prettyprint"><div class=3D"gmai=
l-m_-7912082650157566418subprettyprint"><span style=3D"color:rgb(0,0,136)" =
class=3D"gmail-m_-7912082650157566418styled-by-prettify">template</span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-b=
y-prettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-=
7912082650157566418styled-by-prettify"><</span><span style=3D"color:rgb(=
0,0,136)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">class</s=
pan><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418s=
tyled-by-prettify"> T</span><span style=3D"color:rgb(102,102,0)" class=3D"g=
mail-m_-7912082650157566418styled-by-prettify">></span><span style=3D"co=
lor:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"><b=
r></span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-7912082650157=
566418styled-by-prettify">void</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_-7912082650157566418styled-by-prettify"> swap</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">(</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79120826=
50157566418styled-by-prettify">T</span><span style=3D"color:rgb(102,102,0)"=
class=3D"gmail-m_-7912082650157566418styled-by-prettify">&</span><span=
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-=
prettify"> a</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7=
912082650157566418styled-by-prettify">,</span><span style=3D"color:rgb(0,0,=
0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> T</span><span=
style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled=
-by-prettify">&</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m=
_-7912082650157566418styled-by-prettify"> b</span><span style=3D"color:rgb(=
102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">)</spa=
n><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418sty=
led-by-prettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-m_-7912082650157566418styled-by-prettify">{</span><span style=3D"color:rg=
b(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-79120826501=
57566418styled-by-prettify">if</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_-7912082650157566418styled-by-prettify"> </span><span style=3D"=
color:rgb(0,0,136)" class=3D"gmail-m_-7912082650157566418styled-by-prettify=
">constexpr</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-791208=
2650157566418styled-by-prettify"> </span><span style=3D"color:rgb(102,102,0=
)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">(</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">is_nothrow_relocatable_v</span><span style=3D"color:rgb(102,102,0)"=
class=3D"gmail-m_-7912082650157566418styled-by-prettify"><</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-p=
rettify">T</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-791=
2082650157566418styled-by-prettify">>)</span><span style=3D"color:rgb(0,=
0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> </span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418style=
d-by-prettify">{</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7=
912082650157566418styled-by-prettify"><br>=C2=A0 =C2=A0 a</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">.</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79120826=
50157566418styled-by-prettify">serialize</span><span style=3D"color:rgb(102=
,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">();</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 b</span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">.</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-p=
rettify">serialize</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-m_-7912082650157566418styled-by-prettify">();</span><span style=3D"color:=
rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"><br><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_=
-7912082650157566418styled-by-prettify">byte</span><span style=3D"color:rgb=
(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> pa </spa=
n><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-791208265015756641=
8styled-by-prettify">=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gm=
ail-m_-7912082650157566418styled-by-prettify"> </span><span style=3D"color:=
rgb(0,0,136)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">rein=
terpret_cast</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7=
912082650157566418styled-by-prettify"><</span><span style=3D"color:rgb(0=
,0,136)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">byte</spa=
n><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-791208265015756641=
8styled-by-prettify">*>(&</span><span style=3D"color:rgb(0,0,0)" cla=
ss=3D"gmail-m_-7912082650157566418styled-by-prettify">a</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082=
650157566418styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or:rgb(0,0,136)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">b=
yte</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79120826501575=
66418styled-by-prettify"> pb </span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"gmail-m_-7912082650157566418styled-by-prettify">=3D</span><span styl=
e=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prett=
ify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-791208265=
0157566418styled-by-prettify">reinterpret_cast</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"><=
;</span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-79120826501575=
66418styled-by-prettify">byte</span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"gmail-m_-7912082650157566418styled-by-prettify">*>(&</span><s=
pan style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-=
by-prettify">b</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_=
-7912082650157566418styled-by-prettify">);</span><span style=3D"color:rgb(0=
,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"><br>=C2=A0 =
=C2=A0 <br>=C2=A0 =C2=A0 swap_ranges</span><span style=3D"color:rgb(102,102=
,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">(</span><span=
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-=
prettify">pa</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7=
912082650157566418styled-by-prettify">,</span><span style=3D"color:rgb(0,0,=
0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> pa</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418style=
d-by-prettify">+</span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_=
-7912082650157566418styled-by-prettify">sizeof</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">(</=
span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418=
styled-by-prettify">T</span><span style=3D"color:rgb(102,102,0)" class=3D"g=
mail-m_-7912082650157566418styled-by-prettify">),</span><span style=3D"colo=
r:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> pb<=
/span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-79120826501575=
66418styled-by-prettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D=
"gmail-m_-7912082650157566418styled-by-prettify"><br><br>=C2=A0 =C2=A0 a</s=
pan><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566=
418styled-by-prettify">.</span><span style=3D"color:rgb(0,0,0)" class=3D"gm=
ail-m_-7912082650157566418styled-by-prettify">deserialize</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">();</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-791208=
2650157566418styled-by-prettify"><br>=C2=A0 =C2=A0 b</span><span style=3D"c=
olor:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettif=
y">.</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157=
566418styled-by-prettify">deserialize</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">();</span><s=
pan style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-=
by-prettify"><br>=C2=A0 </span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_-7912082650157566418styled-by-prettify">}</span><span style=3D"=
color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">=
</span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-79120826501575=
66418styled-by-prettify">else</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_-7912082650157566418styled-by-prettify"> </span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pretti=
fy">{</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-791208265015=
7566418styled-by-prettify"><br>=C2=A0 =C2=A0 T c </span><span style=3D"colo=
r:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">=
=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79120826501575=
66418styled-by-prettify"> std</span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"gmail-m_-7912082650157566418styled-by-prettify">::</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-pretti=
fy">move</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-79120=
82650157566418styled-by-prettify">(</span><span style=3D"color:rgb(0,0,0)" =
class=3D"gmail-m_-7912082650157566418styled-by-prettify">a</span><span styl=
e=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-p=
rettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-791208=
2650157566418styled-by-prettify"><br>=C2=A0 =C2=A0 a </span><span style=3D"=
color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pretti=
fy">=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650=
157566418styled-by-prettify"> std</span><span style=3D"color:rgb(102,102,0)=
" class=3D"gmail-m_-7912082650157566418styled-by-prettify">::</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">move</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7=
912082650157566418styled-by-prettify">(</span><span style=3D"color:rgb(0,0,=
0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">b</span><span =
style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-=
by-prettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79=
12082650157566418styled-by-prettify"><br>=C2=A0 =C2=A0 b </span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify">=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-791208=
2650157566418styled-by-prettify"> std</span><span style=3D"color:rgb(102,10=
2,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">::</span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-b=
y-prettify">move</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-=
m_-7912082650157566418styled-by-prettify">(</span><span style=3D"color:rgb(=
0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">c</span><s=
pan style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418sty=
led-by-prettify">);</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m=
_-7912082650157566418styled-by-prettify"><br>=C2=A0 </span><span style=3D"c=
olor:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettif=
y">}</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157=
566418styled-by-prettify"><br></span><span style=3D"color:rgb(102,102,0)" c=
lass=3D"gmail-m_-7912082650157566418styled-by-prettify">}</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-pretti=
fy"><br></span></div></code></div></div></div></blockquote><div><br></div><=
div>Here's P1144's std::swap, for comparison. (Please excuse the li=
bc++-uglification.)</div><div><br></div><div><div>template <class _Tp>=
;</div><div>inline _LIBCPP_INLINE_VISIBILITY</div><div>typename enable_if&l=
t;</div><div>=C2=A0 =C2=A0 is_move_constructible<_Tp>::value &&am=
p;</div><div>=C2=A0 =C2=A0 is_move_assignable<_Tp>::value</div><div>&=
gt;::type</div><div>swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_=
move_constructible<_Tp>::value &&</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 is_nothrow_move_assignable<_Tp>::v=
alue)</div><div>{</div><div>=C2=A0 =C2=A0 if (is_trivially_relocatable<_=
Tp>::value && !is_volatile<_Tp>::value) {</div><div>=C2=A0=
=C2=A0 =C2=A0 =C2=A0 if (!is_empty<_Tp>::value) {</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // TODO: if either __x or __y is a "=
;possibly overlapping subobject"</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 // in Itanium ABI terms, this will memcpy too much data. But=
the</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // same caveat has=
applied to std::copy and friends, since forever.</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 char __t[sizeof (_Tp)];</div><div>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 _VSTD::memcpy(__t, _VSTD::addressof(__x), size=
of(_Tp));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _VSTD::memcpy=
(_VSTD::addressof(__x), _VSTD::addressof(__y), sizeof(_Tp));</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _VSTD::memcpy(_VSTD::addressof(__y),=
__t, sizeof(_Tp));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div>=C2=
=A0 =C2=A0 } else {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Tp __t(_VSTD::mo=
ve(__x));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 __x =3D _VSTD::move(__y);</=
div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 __y =3D _VSTD::move(__t);</div><div>=
=C2=A0 =C2=A0 }</div><div>}</div></div><div><br></div><div>Using std::swap_=
ranges is a neat trick I hadn't thought of; but FWIW, <a href=3D"https:=
//godbolt.org/g/z5kcUY">it doesn't generate quite as nice codegen</a>=
=C2=A0as the simple memcpy AFAICT.</div><div><br></div><div><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-=
width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div>Your code looks like an offset pointer whose range is=
limited. An offset pointer is a tricky question in general.<br></div></div=
></blockquote><div><br></div><div>Yes, it is. Does your proposed library se=
gfault when presented with offset_ptr?=C2=A0 P1144 does not.</div><div><br>=
</div></div></div></div></blockquote><div><br></div></span><div>If offset_p=
tr is made non-relocatable, then my proposed library will not segfault as i=
t will fallback to move.</div></div></blockquote><div><br></div><div>Right.=
So you're defining essentially two routes the user might take here:</d=
iv><div>=C2=A0 =C2=A0 relocate =3D serialize + memcpy + deserialize</div><d=
iv>=C2=A0 =C2=A0 relocate =3D move + destroy</div><div>If the user takes th=
e first route by providing `operator delocate` and `operator relocate`, the=
n your `swap` will use those functions (which may or may not be trivial) br=
acketing a simple memcpy.</div><div>If the user takes the second route by p=
roviding a trivial move-constructor and a trivial destructor, then your `sw=
ap` doesn't-currently,-but-should use a simple memcpy.</div><div><br></=
div><div><br></div><div>[...Switching gears now to talk about "positio=
n-independence"...]</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border=
-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></div>=
<div>If offset_ptr is kept implicitly relocatable, then it will depend on h=
ow it will be used.</div><div>For instance, we can teach people to pointers=
to point outside the object and offset_ptr to point within the object. The=
ir types will then be safely relocatables.</div><div>And if they need a poi=
nter to point within the object or an offset_ptr to point outside the objec=
t, then they would need to define/delete relocation.</div></div></blockquot=
e><div><br></div><div>Right, that's what makes "position-independe=
nce" such a harder problem. The correct semantics for your `operator r=
elocate` depend on how the user is <i>intending to use</i> the offset_ptr o=
bject in question.=C2=A0 Some of the offset_ptrs in their program (the ones=
used inside position-independent memory segments) will be okay with an =3D=
default'ed `operator relocate`, but others (the ones used outside) will=
require `operator relocate` to do some fixup.=C2=A0 This would work great =
if we could somehow attach an `operator relocate` implementation to an obje=
ct at runtime based on how it's being used; but in C++ we have to defin=
e `operator relocate`<i> for the entire type at once</i>. And that's a =
problem, because there is no `operator relocate` that works for the entire =
type =E2=80=94 at least, not as long as you're trying to fit relocation=
and position-independence into the same box.</div><div><br></div><div>As s=
oon as you split up relocation (an operation that can be defined unambiguou=
sly at the type level) from position-independence (an operation that nobody=
knows how to define, yet, except that it's certainly not a property of=
a <i>type</i> in isolation), a good chunk of these problems go away.</div>=
<div><br></div><div><br></div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-sty=
le:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"l=
tr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-le=
ft-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-=
color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></div><div>S=
o I would say the NearPtr shouldn't relocatable to be safe</div></div><=
/blockquote><div><br></div><div>Please describe how your compiler would ens=
ure that NearPtr was <i>not</i> considered trivially fullrelocatable, <i>ye=
t, at the same time</i>, ensure that RedPtr was considered trivially fullre=
locatable.</div></div></div></blockquote><div><br></div></span><div><div st=
yle=3D"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187)"=
class=3D"gmail-m_-7912082650157566418prettyprint"><code class=3D"gmail-m_-=
7912082650157566418prettyprint"><div class=3D"gmail-m_-7912082650157566418s=
ubprettyprint"><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-7912082=
650157566418styled-by-prettify">struct</span><span style=3D"color:rgb(0,0,0=
)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> </span><span s=
tyle=3D"color:rgb(102,0,102)" class=3D"gmail-m_-7912082650157566418styled-b=
y-prettify">NearPtr</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m=
_-7912082650157566418styled-by-prettify"> </span><span style=3D"color:rgb(1=
02,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">{</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styl=
ed-by-prettify"><br>=C2=A0 </span><span style=3D"color:rgb(136,0,0)" class=
=3D"gmail-m_-7912082650157566418styled-by-prettify">/* ... */</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-pr=
ettify"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail=
-m_-7912082650157566418styled-by-prettify">void</span><span style=3D"color:=
rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify"> </spa=
n><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-7912082650157566418s=
tyled-by-prettify">operator</span><span style=3D"color:rgb(0,0,0)" class=3D=
"gmail-m_-7912082650157566418styled-by-prettify"> serialize</span><span sty=
le=3D"color:rgb(102,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-=
prettify">()</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-79120=
82650157566418styled-by-prettify"> </span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">=3D</span><spa=
n style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styled-by=
-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-791=
2082650157566418styled-by-prettify">delete</span><span style=3D"color:rgb(1=
02,102,0)" class=3D"gmail-m_-7912082650157566418styled-by-prettify">;</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-7912082650157566418styl=
ed-by-prettify"><br></span><span style=3D"color:rgb(102,102,0)" class=3D"gm=
ail-m_-7912082650157566418styled-by-prettify">};</span></div></code></div><=
/div></div></blockquote><div><br></div><div>Unfortunately, this requires a =
change to the codebase of NearPtr, based on human input. Some human being h=
as to look at "NearPtr.h", realize that it would invoke UB when c=
ompiled with a C++2a compiler, and add the `=3Ddelete` line =E2=80=94 under=
an #ifdef of course, since that line wouldn't compile as C++17!</div><=
div>But the #ifdef is a minor concern compared to the human being's inv=
olvement. You're basically proposing that in order to upgrade our compi=
ler from C++17 to C++2a, we have to pay a (fairly expert) software engineer=
to comb over all of our header files looking for types that might not be t=
rivially serializable, and add this line to any of them they find. That'=
;s a major code audit that could quite honestly take <i>months</i>, which i=
s to say, tens of thousands of dollars.</div><div><br></div><div>You see th=
e problem, right?</div><div><br></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:soli=
d;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><di=
v>The main problem you are trying to highlight with my design is: either al=
most no types would be made implicitly relocatable, or we will have false-p=
ositive.</div><div>While I agree with this concern, I also want to point th=
at your design has the same defect to a certain extent.<br></div><div>The 4=
cases you expressed are great, but are not bound to a type in the general =
case (it cannot be detected reliably by the compiler).</div></div></blockqu=
ote><div><br></div><div>Yes it can. :) =C2=A0I dare you to find any C++17 c=
ode, anywhere in the world, or even made up ad-hoc just for this purpose, w=
hich is mishandled by <a href=3D"https://godbolt.org/g/oYyHkg">the P1144 co=
mpiler on Godbolt.org.</a></div><div>If you =E2=80=94 or anyone =E2=80=94 f=
ind any such code, please email me off-list to collect a bug bounty. :)</di=
v><div><br></div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2B_9AVCHpBw8ixf82uSoTz4g0b_0z=
nNesFC%3DE_gnULJDA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2B_9A=
VCHpBw8ixf82uSoTz4g0b_0znNesFC%3DE_gnULJDA%40mail.gmail.com</a>.<br />
--000000000000e96fd605734564c5--
.
Author: florian.csdt@gmail.com
Date: Mon, 13 Aug 2018 02:52:58 -0700 (PDT)
Raw View
------=_Part_1425_372287963.1534153978738
Content-Type: multipart/alternative;
boundary="----=_Part_1426_507598749.1534153978739"
------=_Part_1426_507598749.1534153978739
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
@Arthur
I will first answer generally, it will (hopefully) make my explanations=20
easier.
You seem to want all movable types to also be relocatable by saying: if a=
=20
type is not trivially relocatable, then relocate =3D memcpy + destroy.
What I propose is that some types will not be relocatable at all (more on=
=20
this later). And the fallback is written by the user because it highly=20
depends on where relocation is used.
For instance, there is no way to emulate serialize+realloc+deserialize with=
=20
your form of fallback.
As I don't provide any automatic fallback at the language level, the user=
=20
(might be a library writer) will need to write the fallback code themselves=
=20
(here: allocate+move+destroy+deallocate).
So when you say "in my design, T is relocatable", I will now understand: "T=
=20
is movable and non relocatable; serialize+memcpy+deserialize could be=20
emulated by move+destroy".
But I fail to see what you gain from this.
Now about implicit relocation (in my sense).
There is no way to make std::unique_ptr implicitly (trivially) relocatable,=
=20
while also making NearPtr implicitly not relocatable.
I'm almost convinced that, while most types could be made trivially=20
relocatable, and those not safe for that task are only a few, it is safer=
=20
to opt-in more types, than opt-out a few types.
It is basically a trade-off between false positive (non-safe implicitly=20
relocatable) and false negative (implicitly non-relocatable, but would be=
=20
safe).
The rules for implicit serialize/deserialize generation could be:
If a type has (implicitely or explicitly) defaulted move constructor and=20
destructor (or move is not provided and copy is defaulted),=20
serialize/deserialize are generated
In all other cases, serialize/deserialize will not be implicitly generated,=
=20
but can still be explicitly defaulted.
The more I look at these rules, the more I think it is the safest way to do=
=20
it.
Le lundi 13 ao=C3=BBt 2018 01:32:48 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Sun, Aug 12, 2018 at 2:45 AM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>> Le dimanche 12 ao=C3=BBt 2018 02:02:55 UTC+2, Arthur O'Dwyer a =C3=A9cri=
t :
>>>
>>> On Sat, Aug 11, 2018 at 1:32 PM, <floria...@gmail.com> wrote:
>>>
>>>> Le samedi 11 ao=C3=BBt 2018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9cri=
t :
>>>>>
>>>>>
>>>>>
>>>>>
>>> I strongly, strongly suggest that you adopt the verb "relocate" as=20
>>> meaning "deserialize + memcpy + serialize" (that is, replace your "oper=
ator=20
>>> relocate" with an "operator serialize"). That will bring your terminolo=
gy=20
>>> into line with the terminology that has been established in previous=20
>>> discussions in this forum (by myself, Nicol, Niall, Facebook Folly, EAS=
TL,=20
>>> etc.)
>>>
>>
>> I'm not really happy with serialize/deserialize, as it is almost always=
=20
>> used for communication or storage. This is not what I'm proposing is abo=
ut.=20
>> But I'm fine sticking to it until we find better names.
>> Please also note that serialization has the same defect as my previous=
=20
>> naming: the word "serialization" is sometime used to refer to the whole=
=20
>> process.
>>
>> So for now, and until we find better names: relocate =3D serialize +=20
>> deserialize
>>
>
> Okay. (Well, almost. We'll cover that below.)
>
I have the impression you forgot to cover it.
>
> and it is also possible to have copyable movable types that are not=20
>>>>>> relocatable.
>>>>>>
>>>>>
>>>>> ...because you define "relocatable" to mean not just=20
>>>>> "gettable-from-point-A-to-point-B" but "gettable *by this specific=20
>>>>> mechanism* involving `operator relocate`."
>>>>>
>>>> So by your definition, IIUC, std::string would not be relocatable at=
=20
>>>>> all; boost::unique_ptr would not be relocatable at all; folly::FBVect=
or=20
>>>>> would not be relocatable at all...
>>>>>
>>>>
>>>> Of course they would be. Why wouldn't they?
>>>> Those are just pointers, and pointers are trivially relocatable. So th=
e=20
>>>> compiler generated operators delocate/relocate would also be trivially=
=20
>>>> relocatable.
>>>>
>>>
>>> Please explain how you propose to do this for boost::unique_ptr, withou=
t=20
>>> completely breaking std::list.
>>>
>>
>> You do like for move semantic: you go the other way around by defining=
=20
>> explicitly operator serialize/deserialize for std::list.
>>
>
> (snip: an example implementation of std::list with a user-provided move=
=20
> constructor, a user-provided destructor, a user-provided operator delocat=
e,=20
> and a user-provided operator relocate)
>
> Okay, so that would be how you'd *enable* "relocation support" for=20
> std::list.
>
> And if you *didn't* provide any operator delocate or operator relocate=20
> for std::list, then std::list would not be relocatable at all, is that=20
> right?
>
That was not my first thought, but you convinced me that the implicit=20
generation of serialize/deserialize I had was not safe.
So now yes.
=20
>
> Well, boost::unique_ptr has a user-provided move constructor, a=20
> user-provided destructor, and no operator delocate or operator relocate.
> Therefore, by your logic, boost::unique_ptr would not be relocatable at=
=20
> all, is that right?
>
>
Now, yes. It doesn't lead to efficient code, but at least, it is safe (like=
=20
your proposal, actually).
=20
> =20
>
>> Appendix C of P1144=20
>>> <http://quuxplusone.github.io/draft/d1144-object-relocation.html#non-tr=
ivial-samples>=20
>>> will be useful to you; it lists four situations that can make a type=20
>>> non-trivially relocatable.
>>>
>>
>> I agree with those 4 cases. But the compiler cannot reliably detect thos=
e=20
>> (at least not in the general case). The most you could do is make this U=
B=20
>> (which is actually a good idea).
>>
>
> Well, P1144 does better than "make this UB." P1144 actually supports the=
=20
> generic algorithms vector::resize, std::swap, and=20
> std::uninitialized_relocate for *all* move-constructible, destructible=20
> types. These algorithms get compiled into memcpy exactly when it's safe t=
o=20
> do so (by observing the "trivially relocatable" concept), and fall back=
=20
> onto "relocate =3D move + destroy" in the general case.
>
What do you gain from having all movable types relocatable? It is never=20
said that swap only works for relocatable types. What I want to highlight=
=20
is: the fallback depends on the algorithm.
But as we (mostly) agree on what types are trivially relocatable, those=20
algorithms will use the most efficient implementation in the same cases.=20
The safety here comes from the (trivial) relocation concept: if only safe=
=20
types are (trivially) relocatable, then those algorithms will also be safe.
The undefined behaviour was about types with defaulted relocation which fit=
=20
in one of those 4 cases. But your proposal will have the same problem here:
class [[trivially_relocatable]] list {
/* ... */
};
Oups, class invariant depends on this, but type is trivially relocatable.=
=20
This should be made UB (because you cannot prove that the class invariant=
=20
depends on this).
=20
> Please, please, open up Compiler Explorer and play around with it a littl=
e=20
> bit!
> (By P1144's definition, boost::unique_ptr is relocatable but not triviall=
y=20
> relocatable. You can observe this directly on CE.=20
> <https://godbolt.org/g/nHC8GG>)
>
>
> Please explain, in the form of a code sample, how you envision a library=
=20
>>> would take advantage of the fullrelocation operation to speed up a comm=
on=20
>>> operation (such as std::vector::resize or std::swap =E2=80=94 but I'll =
accept=20
>>> different examples too). Remember, your library is not allowed to segfa=
ult=20
>>> when presented with std::list.
>>>
>>
>> Here is swap.
>> std::list will not segfault because we defined operator=20
>> serialize/deserialize for it (see above).
>>
>
> Okay, okay. boost::container::list, then. Let's play fair. :)
> However, I already see from the code that for boost::container::list,=20
> you'll just fall back onto move+destroy (the `else` block). So that's fin=
e=20
> =E2=80=94 no segfault, agreed. :)
> =20
>
>> template <class T>
>> void swap(T& a, T& b) {
>> if constexpr (is_nothrow_relocatable_v<T>) {
>> a.serialize();
>> b.serialize();
>>
>> byte pa =3D reinterpret_cast<byte*>(&a);
>> byte pb =3D reinterpret_cast<byte*>(&b);
>> =20
>> swap_ranges(pa, pa+sizeof(T), pb);
>>
>> a.deserialize();
>> b.deserialize();
>> } else {
>> T c =3D std::move(a);
>> a =3D std::move(b);
>> b =3D std::move(c);
>> }
>> }
>>
>
> Here's P1144's std::swap, for comparison. (Please excuse the=20
> libc++-uglification.)
>
> template <class _Tp>
> inline _LIBCPP_INLINE_VISIBILITY
> typename enable_if<
> is_move_constructible<_Tp>::value &&
> is_move_assignable<_Tp>::value
> >::type
> swap(_Tp& __x, _Tp& __y)=20
> _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value &&
> is_nothrow_move_assignable<_Tp>::valu=
e)
> {
> if (is_trivially_relocatable<_Tp>::value && !is_volatile<_Tp>::value)=
{
> if (!is_empty<_Tp>::value) {
> // TODO: if either __x or __y is a "possibly overlapping=20
> subobject"
> // in Itanium ABI terms, this will memcpy too much data. But=
=20
> the
> // same caveat has applied to std::copy and friends, since=20
> forever.
> char __t[sizeof (_Tp)];
> _VSTD::memcpy(__t, _VSTD::addressof(__x), sizeof(_Tp));
> _VSTD::memcpy(_VSTD::addressof(__x), _VSTD::addressof(__y),=
=20
> sizeof(_Tp));
> _VSTD::memcpy(_VSTD::addressof(__y), __t, sizeof(_Tp));
> }
> } else {
> _Tp __t(_VSTD::move(__x));
> __x =3D _VSTD::move(__y);
> __y =3D _VSTD::move(__t);
> }
> }
>
Your swap is basically the same as mine. Except I can handle user-defined=
=20
relocation.
=20
>
> Using std::swap_ranges is a neat trick I hadn't thought of; but FWIW, it=
=20
> doesn't generate quite as nice codegen <https://godbolt.org/g/z5kcUY> as=
=20
> the simple memcpy AFAICT.
>
>
I wish there were a memswap function. I agree codegen from std::swap_ranges=
=20
is nasty (I didn't try). But codegen from memcpy is not perfect either (a=
=20
third of the memory accesses could be avoided).
The best would be memswap, but that does not exist.
=20
>
>
>>> Your code looks like an offset pointer whose range is limited. An offse=
t=20
>>>> pointer is a tricky question in general.
>>>>
>>>
>>> Yes, it is. Does your proposed library segfault when presented with=20
>>> offset_ptr? P1144 does not.
>>>
>>>
>> If offset_ptr is made non-relocatable, then my proposed library will not=
=20
>> segfault as it will fallback to move.
>>
>
> Right. So you're defining essentially two routes the user might take here=
:
> relocate =3D serialize + memcpy + deserialize
> relocate =3D move + destroy
> If the user takes the first route by providing `operator delocate` and=20
> `operator relocate`, then your `swap` will use those functions (which may=
=20
> or may not be trivial) bracketing a simple memcpy.
> If the user takes the second route by providing a trivial move-constructo=
r=20
> and a trivial destructor, then your `swap` doesn't-currently,-but-should=
=20
> use a simple memcpy.
>
If a user defines a type with trivial move-constructor and trivial=20
destructor, then operator serialize and operator deserialize will be=20
implicitly generated, so the type will be trivially relocatable, so swap=20
will use the "memswap" approach.
If the move-constructor is not trivial, then serialize/deserialize will not=
=20
be generated, and the 3 moves will be used.
If a user follow the rule of 0 (or the rule of 5 defaults), then its type=
=20
will most likely be relocatable, depending on its subobjects=20
(members+bases). And the most efficient implementation of swap (or=20
vector::resize...) satisfying the constraint of the type will be used.
=20
>
>
> [...Switching gears now to talk about "position-independence"...]
>
>> If offset_ptr is kept implicitly relocatable, then it will depend on how=
=20
>> it will be used.
>> For instance, we can teach people to pointers to point outside the objec=
t=20
>> and offset_ptr to point within the object. Their types will then be safe=
ly=20
>> relocatables.
>> And if they need a pointer to point within the object or an offset_ptr t=
o=20
>> point outside the object, then they would need to define/delete relocati=
on.
>>
>
> Right, that's what makes "position-independence" such a harder problem.=
=20
> The correct semantics for your `operator relocate` depend on how the user=
=20
> is *intending to use* the offset_ptr object in question. Some of the=20
> offset_ptrs in their program (the ones used inside position-independent=
=20
> memory segments) will be okay with an =3Ddefault'ed `operator relocate`, =
but=20
> others (the ones used outside) will require `operator relocate` to do som=
e=20
> fixup. This would work great if we could somehow attach an `operator=20
> relocate` implementation to an object at runtime based on how it's being=
=20
> used; but in C++ we have to define `operator relocate`* for the entire=20
> type at once*. And that's a problem, because there is no `operator=20
> relocate` that works for the entire type =E2=80=94 at least, not as long =
as you're=20
> trying to fit relocation and position-independence into the same box.
>
The difference here will have to be coded in the wrapping type. But that is=
=20
possible even if the offset_ptr is non relocatable.
So I think an offset_ptr shouldn't be made relocatable, and if the user=20
uses it inside its type and wants to make their type relocatable, they will=
=20
need to implement serialize/deserialize.
=20
>
> As soon as you split up relocation (an operation that can be defined=20
> unambiguously at the type level) from position-independence (an operation=
=20
> that nobody knows how to define, yet, except that it's certainly not a=20
> property of a *type* in isolation), a good chunk of these problems go=20
> away.
>
I agree.
=20
>
>
>
> So I would say the NearPtr shouldn't relocatable to be safe
>>>>
>>>
>>> Please describe how your compiler would ensure that NearPtr was *not*=
=20
>>> considered trivially fullrelocatable, *yet, at the same time*, ensure=
=20
>>> that RedPtr was considered trivially fullrelocatable.
>>>
>>
>> struct NearPtr {
>> /* ... */
>> void operator serialize() =3D delete;
>> };
>>
>
> Unfortunately, this requires a change to the codebase of NearPtr, based o=
n=20
> human input. Some human being has to look at "NearPtr.h", realize that it=
=20
> would invoke UB when compiled with a C++2a compiler, and add the `=3Ddele=
te`=20
> line =E2=80=94 under an #ifdef of course, since that line wouldn't compil=
e as C++17!
> But the #ifdef is a minor concern compared to the human being's=20
> involvement. You're basically proposing that in order to upgrade our=20
> compiler from C++17 to C++2a, we have to pay a (fairly expert) software=
=20
> engineer to comb over all of our header files looking for types that migh=
t=20
> not be trivially serializable, and add this line to any of them they find=
..=20
> That's a major code audit that could quite honestly take *months*, which=
=20
> is to say, tens of thousands of dollars.
>
> You see the problem, right?
>
Yes, that's why I changed the rules of implicit generation (Thank you to=20
have pointed me out this issue).
=20
>
> The main problem you are trying to highlight with my design is: either=20
>> almost no types would be made implicitly relocatable, or we will have=20
>> false-positive.
>> While I agree with this concern, I also want to point that your design=
=20
>> has the same defect to a certain extent.
>> The 4 cases you expressed are great, but are not bound to a type in the=
=20
>> general case (it cannot be detected reliably by the compiler).
>>
>
> Yes it can. :) I dare you to find any C++17 code, anywhere in the world,=
=20
> or even made up ad-hoc just for this purpose, which is mishandled by the=
=20
> P1144 compiler on Godbolt.org. <https://godbolt.org/g/oYyHkg>
> If you =E2=80=94 or anyone =E2=80=94 find any such code, please email me =
off-list to=20
> collect a bug bounty. :)
>
> =E2=80=93Arthur
>
It can because we don't share the same definition of relocation. You insist=
=20
in having relocation meaning move+destroy. But that's not what I propose.
With what I propose, relocation is not about memcpy; it is not about=20
move+destroy. It is about processing the object to be able to change its=20
location by an external mean.
This cannot be emulated with move+destroy in the general case (because it=
=20
highly depends of what is this external mean).
If a type does not support such an operation, that's fine: don't use it.=20
But don't pretend it is supported, and do something else in the back.
If you want move+destroy, use move+destroy. If you want either=20
memcpy+relocation or move+destroy depending on what the type supports, then=
=20
write a function that is either memcpy+relocation or move+destroy (we can=
=20
propose this one as part of the STL, and/or an optimization the compiler=20
will be able to do).
Basically, when you say "relocatable", you just say "movable", and only=20
trivially relocatable has a special meaning. That's not something I find=20
useful.
That's why I propose "relocatable" meaning the object can be processed in=
=20
such a way that we can change its location by any means we see fit. This=20
relocation can also be trivial (making it basically a noop).
Most types will not be relocatables by default: fine, each algorithm that=
=20
can use relocation to be more efficient will use its own fallback to=20
support non-relocatable types. If an algorithm is not written to take=20
advantage of relocation, that's also fine as relocation doesn't change the=
=20
rules for copy/move/destruct an object.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/4eaa325d-8818-4c98-bb9f-bd9e0ca09e1a%40isocpp.or=
g.
------=_Part_1426_507598749.1534153978739
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">@Arthur<br>I will first answer generally, it will (hopeful=
ly) make my explanations easier.<br><br>You seem to want all movable types =
to also be relocatable by saying: if a type is not trivially relocatable, t=
hen relocate =3D memcpy + destroy.<br>What I propose is that some types wil=
l not be relocatable at all (more on this later). And the fallback is writt=
en by the user because it highly depends on where relocation is used.<br>Fo=
r instance, there is no way to emulate serialize+realloc+deserialize with y=
our form of fallback.<br>As I don't provide any automatic fallback at t=
he language level, the user (might be a library writer) will need to write =
the fallback code themselves (here: allocate+move+destroy+deallocate).<br><=
br>So when you say "in my design, T is relocatable", I will now u=
nderstand: "T is movable and non relocatable; serialize+memcpy+deseria=
lize could be emulated by move+destroy".<br>But I fail to see what you=
gain from this.<br><br>Now about implicit relocation (in my sense).<br>The=
re is no way to make std::unique_ptr implicitly (trivially) relocatable, wh=
ile also making NearPtr implicitly not relocatable.<br>I'm almost convi=
nced that, while most types could be made trivially relocatable, and those =
not safe for that task are only a few, it is safer to opt-in more types, th=
an opt-out a few types.<br>It is basically a trade-off between false positi=
ve (non-safe implicitly relocatable) and false negative (implicitly non-rel=
ocatable, but would be safe).<br><br>The rules for implicit serialize/deser=
ialize generation could be:<br>If a type has (implicitely or explicitly) de=
faulted move constructor and destructor (or move is not provided and copy i=
s defaulted), serialize/deserialize are generated<br>In all other cases, se=
rialize/deserialize will not be implicitly generated, but can still be expl=
icitly defaulted.<br><br>The more I look at these rules, the more I think i=
t is the safest way to do it.<br><br>Le lundi 13 ao=C3=BBt 2018 01:32:48 UT=
C+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div dir=3D"ltr">On Sun, Aug 12, 2018 at 2:45 AM, <span dir=
=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailt=
o=3D"CYczzzr-DQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;">floria...@gmail.com</a>></span> wrote:<div><div class=3D"gmail_q=
uote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr">Le dimanche 12 ao=C3=BBt 2018 02:02=
:55 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;borde=
r-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><di=
v dir=3D"ltr">On Sat, Aug 11, 2018 at 1:32 PM, <span dir=3D"ltr"><<a re=
l=3D"nofollow">floria...@gmail.com</a>></span> wrote:<br><div><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Le samedi 11 ao=C3=BBt 2=
018 20:57:25 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>=
<br></div></div></div></div></blockquote></span></div></blockquote></div></=
div></div></blockquote></span><span><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>=
<div class=3D"gmail_quote"><div><br></div><div>I strongly, strongly suggest=
that you adopt the verb "relocate" as meaning "deserialize =
+ memcpy + serialize" (that is, replace your "operator relocate&q=
uot; with an "operator serialize"). That will bring your terminol=
ogy into line with the terminology that has been established in previous di=
scussions in this forum (by myself, Nicol, Niall, Facebook Folly, EASTL, et=
c.)</div></div></div></div></blockquote><br></span>I'm not really happy=
with serialize/deserialize, as it is almost always used for communication =
or storage. This is not what I'm proposing is about. But I'm fine s=
ticking to it until we find better names.<br>Please also note that serializ=
ation has the same defect as my previous naming: the word "serializati=
on" is sometime used to refer to the whole process.<br><br>So for now,=
and until we find better names: relocate =3D serialize + deserialize</div>=
</blockquote><div><br></div><div>Okay. (Well, almost. We'll cover that =
below.)</div></div></div></div></blockquote><div><br></div><div>I have the =
impression you forgot to cover it.</div><div> <br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bord=
er-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padd=
ing-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-l=
eft-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color=
:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div> and it is also p=
ossible to have copyable movable types that are not relocatable.</div></div=
></blockquote><div><br></div><div>...because you define "relocatable&q=
uot; to mean not just "gettable-from-point-A-to-<wbr>point-B" but=
"gettable <i>by this specific mechanism</i> involving `operator reloc=
ate`."</div></div></div></div></blockquote></span><span><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px=
;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1e=
x"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=C2=A0So by your d=
efinition, IIUC, std::string would not be relocatable at all; boost::unique=
_ptr would not be relocatable at all; folly::FBVector would not be relocata=
ble at all...</div></div></div></div></blockquote><div><br></div></span><di=
v>Of course they would be. Why wouldn't they?</div><div>Those are just =
pointers, and pointers are trivially relocatable. So the compiler generated=
operators delocate/relocate would also be trivially relocatable.</div></di=
v></blockquote><div><br></div><div>Please explain how you propose to do thi=
s for boost::unique_ptr, without completely breaking std::list.</div></div>=
</div></div></blockquote><div><br></div></span><div>You do like for move se=
mantic: you go the other way around by defining explicitly operator seriali=
ze/deserialize for std::list.</div></div></blockquote><div><br></div><div>(=
snip: an example implementation of std::list with a user-provided move cons=
tructor, a user-provided destructor, a user-provided operator delocate, and=
a user-provided operator relocate)</div><div><br></div><div>Okay, so that =
would be how you'd <i>enable</i> "relocation support" for std=
::list.</div><div><br></div><div>And if you <i>didn't</i> provide any o=
perator delocate or operator relocate for std::list, then std::list would n=
ot be relocatable at all, is that right?</div></div></div></div></blockquot=
e><div><br></div><div>That was not my first thought, but you convinced me t=
hat the implicit generation of serialize/deserialize I had was not safe.</d=
iv><div>So now yes.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br><=
/div><div>Well, boost::unique_ptr has a user-provided move constructor, a u=
ser-provided destructor, and no operator delocate or operator relocate.</di=
v><div>Therefore, by your logic, boost::unique_ptr would not be relocatable=
at all, is that right?</div><div><br></div></div></div></div></blockquote>=
<div><br></div><div>Now, yes. It doesn't lead to efficient code, but at=
least, it is safe (like your proposal, actually).<br></div><div>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left=
-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb=
(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_q=
uote"><div><a href=3D"http://quuxplusone.github.io/draft/d1144-object-reloc=
ation.html#non-trivial-samples" rel=3D"nofollow" target=3D"_blank" onmoused=
own=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxplu=
sone.github.io%2Fdraft%2Fd1144-object-relocation.html%23non-trivial-samples=
\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHGMNg6-Yx1BjiEE1MetwX2kUWFPA';=
return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\x3dht=
tp%3A%2F%2Fquuxplusone.github.io%2Fdraft%2Fd1144-object-relocation.html%23n=
on-trivial-samples\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHGMNg6-Yx1BjiEE1=
MetwX2kUWFPA';return true;">Appendix C of P1144</a> will be useful to y=
ou; it lists four situations that can make a type non-trivially relocatable=
..</div></div></div></div></blockquote><div><br></div></span><div>I agree wi=
th those 4 cases. But the compiler cannot reliably detect those (at least n=
ot in the general case). The most you could do is make this UB (which is ac=
tually a good idea).<br></div></div></blockquote><div><br></div><div>Well, =
P1144 does better than "make this UB." =C2=A0P1144 actually suppo=
rts the generic algorithms vector::resize, std::swap, and std::uninitialize=
d_relocate for <i>all</i> move-constructible, destructible types. These alg=
orithms get compiled into memcpy exactly when it's safe to do so (by ob=
serving the "trivially relocatable" concept), and fall back onto =
"relocate =3D move + destroy" in the general case.</div></div></d=
iv></div></blockquote><div><br></div><div>What do you gain from having all =
movable types relocatable? It is never said that swap only works for reloca=
table types. What I want to highlight is: the fallback depends on the algor=
ithm.</div><div>But as we (mostly) agree on what types are trivially reloca=
table, those algorithms will use the most efficient implementation in the s=
ame cases. The safety here comes from the (trivial) relocation concept: if =
only safe types are (trivially) relocatable, then those algorithms will als=
o be safe.</div><div><br></div><div>The undefined behaviour was about types=
with defaulted relocation which fit in one of those 4 cases. But your prop=
osal will have the same problem here:</div><div><div style=3D"background-co=
lor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: so=
lid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">[[</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">trivially_relocatable</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">]]</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> list </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">/* ... */</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span></div></code></div>Oups, class invariant depends on this, but type is =
trivially relocatable. This should be made UB (because you cannot prove tha=
t the class invariant depends on this).<br><br></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote"><div>Please, please, open up Compiler Explorer and play aroun=
d with it a little bit!</div><div>(By P1144's definition, boost::unique=
_ptr is relocatable but not trivially relocatable. <a href=3D"https://godbo=
lt.org/g/nHC8GG" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FnH=
C8GG\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEE-6jRqu0mi_Z8mRtL1kkze7y4Og&#=
39;;return true;" onclick=3D"this.href=3D'https://www.google.com/url?q\=
x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FnHC8GG\x26sa\x3dD\x26sntz\x3d1\x26usg\x3=
dAFQjCNEE-6jRqu0mi_Z8mRtL1kkze7y4Og';return true;">You can observe this=
directly on CE.</a>)</div><div><br></div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-c=
olor:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote"><div>Please explain, in the form of a code sample, how you en=
vision a library would take advantage of the fullrelocation operation to sp=
eed up a common operation (such as std::vector::resize or std::swap =E2=80=
=94 but I'll accept different examples too). Remember, your library is =
not allowed to segfault when presented with std::list.</div></div></div></d=
iv></blockquote><div><br></div></span><div>Here is swap.</div><div>std::lis=
t will not segfault because we defined operator serialize/deserialize for i=
t (see above).<br></div></div></blockquote><div><br></div><div>Okay, okay. =
boost::container::list, then.=C2=A0 Let's play fair. :)</div><div>Howev=
er, I already see from the code that for boost::container::list, you'll=
just fall back onto move+destroy (the `else` block). So that's fine =
=E2=80=94 no segfault, agreed. :)</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div></div><div><div style=3D"background-color:rgb(250,250=
,250);border:1px solid rgb(187,187,187)"><code><div><span style=3D"color:rg=
b(0,0,136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)"=
>class</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color=
:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><sp=
an style=3D"color:rgb(0,0,136)">void</span><span style=3D"color:rgb(0,0,0)"=
> swap</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"co=
lor:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&</span><s=
pan style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(102,102,0)=
">,</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rg=
b(102,102,0)">&</span><span style=3D"color:rgb(0,0,0)"> b</span><span s=
tyle=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0=
,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">if</span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">const=
expr</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">is_nothrow_relocatab=
le_v</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"c=
olor:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">>)</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)=
">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 a</span><span =
style=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">ser=
ialize</span><span style=3D"color:rgb(102,102,0)">();</span><span style=3D"=
color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 b</span><span style=3D"color:rgb(102,10=
2,0)">.</span><span style=3D"color:rgb(0,0,0)">serialize</span><span style=
=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"><br><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">byte</span><span =
style=3D"color:rgb(0,0,0)"> pa </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">reinterpret_cast</span><span style=3D"color:rgb(102,102,0)"><=
</span><span style=3D"color:rgb(0,0,136)">byte</span><span style=3D"color:r=
gb(102,102,0)">*>(&</span><span style=3D"color:rgb(0,0,0)">a</span><=
span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0=
)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">byte</span><=
span style=3D"color:rgb(0,0,0)"> pb </span><span style=3D"color:rgb(102,102=
,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(0,0,136)">reinterpret_cast</span><span style=3D"color:rgb(102,102,0)"=
><</span><span style=3D"color:rgb(0,0,136)">byte</span><span style=3D"co=
lor:rgb(102,102,0)">*>(&</span><span style=3D"color:rgb(0,0,0)">b</s=
pan><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(=
0,0,0)"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 swap_ranges</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">pa</span=
><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,=
0)"> pa</span><span style=3D"color:rgb(102,102,0)">+</span><span style=3D"c=
olor:rgb(0,0,136)">sizeof</span><span style=3D"color:rgb(102,102,0)">(</spa=
n><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102=
,0)">),</span><span style=3D"color:rgb(0,0,0)"> pb</span><span style=3D"col=
or:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0=
=C2=A0 a</span><span style=3D"color:rgb(102,102,0)">.</span><span style=3D=
"color:rgb(0,0,0)">deserialize</span><span style=3D"color:rgb(102,102,0)">(=
);</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 b</span><span s=
tyle=3D"color:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">dese=
rialize</span><span style=3D"color:rgb(102,102,0)">();</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102,0)">}=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,=
0,136)">else</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"=
color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =
=C2=A0 T c </span><span style=3D"color:rgb(102,102,0)">=3D</span><span styl=
e=3D"color:rgb(0,0,0)"> std</span><span style=3D"color:rgb(102,102,0)">::</=
span><span style=3D"color:rgb(0,0,0)">move</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span><span style=3D"=
color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =
=C2=A0 a </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=
=3D"color:rgb(0,0,0)"> std</span><span style=3D"color:rgb(102,102,0)">::</s=
pan><span style=3D"color:rgb(0,0,0)">move</span><span style=3D"color:rgb(10=
2,102,0)">(</span><span style=3D"color:rgb(0,0,0)">b</span><span style=3D"c=
olor:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =
=C2=A0 b </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=
=3D"color:rgb(0,0,0)"> std</span><span style=3D"color:rgb(102,102,0)">::</s=
pan><span style=3D"color:rgb(0,0,0)">move</span><span style=3D"color:rgb(10=
2,102,0)">(</span><span style=3D"color:rgb(0,0,0)">c</span><span style=3D"c=
olor:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 <=
/span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb=
(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">}</span><span styl=
e=3D"color:rgb(0,0,0)"><br></span></div></code></div></div></div></blockquo=
te><div><br></div><div>Here's P1144's std::swap, for comparison. (P=
lease excuse the libc++-uglification.)</div><div><br></div><div><div>templa=
te <class _Tp></div><div>inline _LIBCPP_INLINE_VISIBILITY</div><div>t=
ypename enable_if<</div><div>=C2=A0 =C2=A0 is_move_constructible<_Tp&=
gt;::<wbr>value &&</div><div>=C2=A0 =C2=A0 is_move_assignable<_T=
p>::value</div><div>>::type</div><div>swap(_Tp& __x, _Tp& __y=
) _NOEXCEPT_(is_nothrow_move_<wbr>constructible<_Tp>::value &&=
;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 is_nothrow_m=
ove_assignable<_<wbr>Tp>::value)</div><div>{</div><div>=C2=A0 =C2=A0 =
if (is_trivially_relocatable<_Tp><wbr>::value && !is_volatile=
<_Tp>::value) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!is_empty&l=
t;_Tp>::value) {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // =
TODO: if either __x or __y is a "possibly overlapping subobject"<=
/div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // in Itanium ABI terms=
, this will memcpy too much data. But the</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 // same caveat has applied to std::copy and friends, s=
ince forever.</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 char __t[=
sizeof (_Tp)];</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _VSTD::m=
emcpy(__t, _VSTD::addressof(__x), sizeof(_Tp));</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 _VSTD::memcpy(_VSTD::<wbr>addressof(__x), _VSTD::a=
ddressof(__y), sizeof(_Tp));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _VSTD::memcpy(_VSTD::<wbr>addressof(__y), __t, sizeof(_Tp));</div><d=
iv>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 } else {</div><div=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Tp __t(_VSTD::move(__x));</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 __x =3D _VSTD::move(__y);</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 __y =3D _VSTD::move(__t);</div><div>=C2=A0 =C2=A0 }</div><div>}<=
/div></div></div></div></div></blockquote><div><br></div><div>Your swap is =
basically the same as mine. Except I can handle user-defined relocation.<br=
></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>Using std::s=
wap_ranges is a neat trick I hadn't thought of; but FWIW, <a href=3D"ht=
tps://godbolt.org/g/z5kcUY" target=3D"_blank" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.=
org%2Fg%2Fz5kcUY\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGpd6Gf9ZzRBfgV7jnL=
qgmGtpzHXQ';return true;" onclick=3D"this.href=3D'https://www.googl=
e.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2Fz5kcUY\x26sa\x3dD\x26sntz\x3=
d1\x26usg\x3dAFQjCNGpd6Gf9ZzRBfgV7jnLqgmGtpzHXQ';return true;">it doesn=
't generate quite as nice codegen</a>=C2=A0as the simple memcpy AFAICT.=
</div><div><br></div></div></div></div></blockquote><div><br></div><div>I w=
ish there were a memswap function. I agree codegen from std::swap_ranges is=
nasty (I didn't try). But codegen from memcpy is not perfect either (a=
third of the memory accesses could be avoided).</div><div>The best would b=
e memswap, but that does not exist.<br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_q=
uote"><div></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bord=
er-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padd=
ing-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204=
);padding-left:1ex"><div dir=3D"ltr"><div>Your code looks like an offset po=
inter whose range is limited. An offset pointer is a tricky question in gen=
eral.<br></div></div></blockquote><div><br></div><div>Yes, it is. Does your=
proposed library segfault when presented with offset_ptr?=C2=A0 P1144 does=
not.</div><div><br></div></div></div></div></blockquote><div><br></div></s=
pan><div>If offset_ptr is made non-relocatable, then my proposed library wi=
ll not segfault as it will fallback to move.</div></div></blockquote><div><=
br></div><div>Right. So you're defining essentially two routes the user=
might take here:</div><div>=C2=A0 =C2=A0 relocate =3D serialize + memcpy +=
deserialize</div><div>=C2=A0 =C2=A0 relocate =3D move + destroy</div><div>=
If the user takes the first route by providing `operator delocate` and `ope=
rator relocate`, then your `swap` will use those functions (which may or ma=
y not be trivial) bracketing a simple memcpy.</div><div>If the user takes t=
he second route by providing a trivial move-constructor and a trivial destr=
uctor, then your `swap` doesn't-currently,-but-should use a simple memc=
py.</div></div></div></div></blockquote><div><br></div><div>If a user defin=
es a type with trivial move-constructor and trivial destructor, then operat=
or serialize and operator deserialize will be implicitly generated, so the =
type will be trivially relocatable, so swap will use the "memswap"=
; approach.</div><div>If the move-constructor is not trivial, then serializ=
e/deserialize will not be generated, and the 3 moves will be used.</div><di=
v><br></div><div>If a user follow the rule of 0 (or the rule of 5 defaults)=
, then its type will most likely be relocatable, depending on its subobject=
s (members+bases). And the most efficient implementation of swap (or vector=
::resize...) satisfying the constraint of the type will be used.<br></div><=
div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div><br></div><div><br></div><div>[...S=
witching gears now to talk about "position-independence"...]</div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);=
padding-left:1ex"><div dir=3D"ltr"><div></div><div>If offset_ptr is kept im=
plicitly relocatable, then it will depend on how it will be used.</div><div=
>For instance, we can teach people to pointers to point outside the object =
and offset_ptr to point within the object. Their types will then be safely =
relocatables.</div><div>And if they need a pointer to point within the obje=
ct or an offset_ptr to point outside the object, then they would need to de=
fine/delete relocation.</div></div></blockquote><div><br></div><div>Right, =
that's what makes "position-independence" such a harder probl=
em. The correct semantics for your `operator relocate` depend on how the us=
er is <i>intending to use</i> the offset_ptr object in question.=C2=A0 Some=
of the offset_ptrs in their program (the ones used inside position-indepen=
dent memory segments) will be okay with an =3Ddefault'ed `operator relo=
cate`, but others (the ones used outside) will require `operator relocate` =
to do some fixup.=C2=A0 This would work great if we could somehow attach an=
`operator relocate` implementation to an object at runtime based on how it=
's being used; but in C++ we have to define `operator relocate`<i> for =
the entire type at once</i>. And that's a problem, because there is no =
`operator relocate` that works for the entire type =E2=80=94 at least, not =
as long as you're trying to fit relocation and position-independence in=
to the same box.</div></div></div></div></blockquote><div><br></div><div>Th=
e difference here will have to be coded in the wrapping type. But that is p=
ossible even if the offset_ptr is non relocatable.</div><div>So I think an =
offset_ptr shouldn't be made relocatable, and if the user uses it insid=
e its type and wants to make their type relocatable, they will need to impl=
ement serialize/deserialize.<br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><=
div><br></div><div>As soon as you split up relocation (an operation that ca=
n be defined unambiguously at the type level) from position-independence (a=
n operation that nobody knows how to define, yet, except that it's cert=
ainly not a property of a <i>type</i> in isolation), a good chunk of these =
problems go away.</div></div></div></div></blockquote><div><br></div><div>I=
agree.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>=
<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left=
-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><blockquot=
e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width=
:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-lef=
t:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1=
ex"><div dir=3D"ltr"><div></div><div>So I would say the NearPtr shouldn'=
;t relocatable to be safe</div></div></blockquote><div><br></div><div>Pleas=
e describe how your compiler would ensure that NearPtr was <i>not</i> consi=
dered trivially fullrelocatable, <i>yet, at the same time</i>, ensure that =
RedPtr was considered trivially fullrelocatable.</div></div></div></blockqu=
ote><div><br></div></span><div><div style=3D"background-color:rgb(250,250,2=
50);border:1px solid rgb(187,187,187)"><code><div><span style=3D"color:rgb(=
0,0,136)">struct</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,0,102)">NearPtr</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(136,0,0)">/* ... */</sp=
an><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:=
rgb(0,0,136)">void</span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(0,0,136)">operator</span><span style=3D"color:rgb(0,0,0)"> =
serialize</span><span style=3D"color:rgb(102,102,0)">()</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</spa=
n><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136=
)">delete</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D=
"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</span=
></div></code></div></div></div></blockquote><div><br></div><div>Unfortunat=
ely, this requires a change to the codebase of NearPtr, based on human inpu=
t. Some human being has to look at "NearPtr.h", realize that it w=
ould invoke UB when compiled with a C++2a compiler, and add the `=3Ddelete`=
line =E2=80=94 under an #ifdef of course, since that line wouldn't com=
pile as C++17!</div><div>But the #ifdef is a minor concern compared to the =
human being's involvement. You're basically proposing that in order=
to upgrade our compiler from C++17 to C++2a, we have to pay a (fairly expe=
rt) software engineer to comb over all of our header files looking for type=
s that might not be trivially serializable, and add this line to any of the=
m they find. That's a major code audit that could quite honestly take <=
i>months</i>, which is to say, tens of thousands of dollars.</div><div><br>=
</div><div>You see the problem, right?</div></div></div></div></blockquote>=
<div><br></div><div>Yes, that's why I changed the rules of implicit gen=
eration (Thank you to have pointed me out this issue).<br></div><div>=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote"><div><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:so=
lid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><=
div>The main problem you are trying to highlight with my design is: either =
almost no types would be made implicitly relocatable, or we will have false=
-positive.</div><div>While I agree with this concern, I also want to point =
that your design has the same defect to a certain extent.<br></div><div>The=
4 cases you expressed are great, but are not bound to a type in the genera=
l case (it cannot be detected reliably by the compiler).</div></div></block=
quote><div><br></div><div>Yes it can. :) =C2=A0I dare you to find any C++17=
code, anywhere in the world, or even made up ad-hoc just for this purpose,=
which is mishandled by <a href=3D"https://godbolt.org/g/oYyHkg" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google=
..com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FoYyHkg\x26sa\x3dD\x26sntz\x3d=
1\x26usg\x3dAFQjCNHufshFrFsXBlZK0wFOYR-qvcfHgA';return true;" onclick=
=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.=
org%2Fg%2FoYyHkg\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHufshFrFsXBlZK0wFO=
YR-qvcfHgA';return true;">the P1144 compiler on Godbolt.org.</a></div><=
div>If you =E2=80=94 or anyone =E2=80=94 find any such code, please email m=
e off-list to collect a bug bounty. :)</div><div><br></div><div>=E2=80=93Ar=
thur</div></div></div></div></blockquote><div><br></div><div>It can because=
we don't share the same definition of relocation. You insist in having=
relocation meaning move+destroy. But that's not what I propose.</div><=
div>With what I propose, relocation is not about memcpy; it is not about mo=
ve+destroy. It is about processing the object to be able to change its loca=
tion by an external mean.</div><div>This cannot be emulated with move+destr=
oy in the general case (because it highly depends of what is this external =
mean).</div><div>If a type does not support such an operation, that's f=
ine: don't use it. But don't pretend it is supported, and do someth=
ing else in the back.</div><div>If you want move+destroy, use move+destroy.=
If you want either memcpy+relocation or move+destroy depending on what the=
type supports, then write a function that is either memcpy+relocation or m=
ove+destroy (we can propose this one as part of the STL, and/or an optimiza=
tion the compiler will be able to do).<br></div><div><br></div><div>Basical=
ly, when you say "relocatable", you just say "movable",=
and only trivially relocatable has a special meaning. That's not somet=
hing I find useful.</div><div>That's why I propose "relocatable&qu=
ot; meaning the object can be processed in such a way that we can change it=
s location by any means we see fit. This relocation can also be trivial (ma=
king it basically a noop).</div><div>Most types will not be relocatables by=
default: fine, each algorithm that can use relocation to be more efficient=
will use its own fallback to support non-relocatable types. If an algorith=
m is not written to take advantage of relocation, that's also fine as r=
elocation doesn't change the rules for copy/move/destruct an object.<br=
></div><div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4eaa325d-8818-4c98-bb9f-bd9e0ca09e1a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4eaa325d-8818-4c98-bb9f-bd9e0ca09e1a=
%40isocpp.org</a>.<br />
------=_Part_1426_507598749.1534153978739--
------=_Part_1425_372287963.1534153978738--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Mon, 13 Aug 2018 13:34:08 -0700
Raw View
--000000000000f8b1ec05735703ff
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Mon, Aug 13, 2018 at 2:52 AM, <florian.csdt@gmail.com> wrote:
>
> You seem to want all movable types to also be relocatable by saying: if a
> type is not trivially relocatable, then relocate =3D memcpy + destroy.
> What I propose is that some types will not be relocatable at all (more on
> this later). And the fallback is written by the user because it highly
> depends on where relocation is used.
> For instance, there is no way to emulate serialize+realloc+deserialize
> with your form of fallback.
> As I don't provide any automatic fallback at the language level, the user
> (might be a library writer) will need to write the fallback code themselv=
es
> (here: allocate+move+destroy+deallocate).
>
> So when you say "in my design, T is relocatable", I will now understand:
> "T is movable and non relocatable; serialize+memcpy+deserialize could be
> emulated by move+destroy".
> But I fail to see what you gain from this.
>
Our definitions are converging! This is good news. :)
I am not too worried that you fail to see what we gain from P1144's
definition of relocation (over yours), because vice versa I fail to see
what we gain from your definition of relocation (over P1144's). I think
that as we plug the holes in your definition, it is quickly converging to
*almost* the same thing as P1144; therefore both definitions have just
about the same advantages and disadvantages. The only thing I would tout as
a remaining major advantage of P1144 is that it has a proposal with wording
and a complete implementation on Godbolt =E2=80=94 and I will happily admit=
that
this is purely circumstantial and does not necessarily indicate that yours
*couldn't* have such an implementation (now that most of the holes are
plugged).
Meanwhile, over in SG14 Nicol and I have just been discussing
std::bless/std::unbless
<https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s4FWah0qCwAJ=
>
and seem to be converging on something very similar to what you and I are
now calling serialize/deserialize! (Except that this hypothetical
bless/unbless cannot be user-provided and must be no-ops.)
Now about implicit relocation (in my sense).
> There is no way to make std::unique_ptr implicitly (trivially)
> relocatable, while also making NearPtr implicitly not relocatable.
> I'm almost convinced that, while most types could be made trivially
> relocatable, and those not safe for that task are only a few, it is safer
> to opt-in more types, than opt-out a few types.
> It is basically a trade-off between false positive (non-safe implicitly
> relocatable) and false negative (implicitly non-relocatable, but would be
> safe).
>
I agree that it is a trade-off. And I agree that opt-in (such as P1144's
attribute [[trivially_relocatable]]) is better than opt-out. (In fact, I
strongly believe that opt-out is a non-starter.) This was one of our major
points of disagreement originally, and I am happy to see that it appears to
be resolved.
> The rules for implicit serialize/deserialize generation could be:
> If a type has (implicitely or explicitly) defaulted move constructor and
> destructor (or move is not provided and copy is defaulted),
> serialize/deserialize are generated
> In all other cases, serialize/deserialize will not be implicitly
> generated, but can still be explicitly defaulted.
>
If you follow down this path, you'll reach P1144's proposed wording, except
that where P1144 says
<https://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-i=
nheritance>
"...or a class type declared with the [[trivially_relocatable]] attribute,"
you'll say "...or a class type with a trivial `operator serialize` *and* a
trivial `operator deserialize`."
Notice that I said "trivial", not just "explicitly defaulted", because I
guess that the default `operator {de,}serialize` should call the `operator
{de,}serialize` of the base classes and members, perhaps? Or do you want
`=3Ddefault` to *always* mean "no-op" even if some bases are non-trivially
relocatable?
[...]
> (snip: an example implementation of std::list with a user-provided move
>> constructor, a user-provided destructor, a user-provided operator deloca=
te,
>> and a user-provided operator relocate)
>>
>> Okay, so that would be how you'd *enable* "relocation support" for
>> std::list.
>>
>> And if you *didn't* provide any operator delocate or operator relocate
>> for std::list, then std::list would not be relocatable at all, is that
>> right?
>>
>
> That was not my first thought, but you convinced me that the implicit
> generation of serialize/deserialize I had was not safe.
> So now yes.
>
Okay, good. Hole plugged. :)
Well, boost::unique_ptr has a user-provided move constructor, a
>> user-provided destructor, and no operator delocate or operator relocate.
>> Therefore, by your logic, boost::unique_ptr would not be relocatable at
>> all, is that right?
>>
>
> Now, yes. It doesn't lead to efficient code, but at least, it is safe
> (like your proposal, actually).
>
Okay, good. :)
[...]
> P1144 actually supports the generic algorithms vector::resize, std::swap,
>> and std::uninitialized_relocate for *all* move-constructible,
>> destructible types. These algorithms get compiled into memcpy exactly wh=
en
>> it's safe to do so (by observing the "trivially relocatable" concept), a=
nd
>> fall back onto "relocate =3D move + destroy" in the general case.
>>
>
> What do you gain from having all movable types relocatable? It is never
> said that swap only works for relocatable types.
>
What you gain is fewer branches in practice. Your `swap` has to say
- if it's trivially relocatable, then memcpy + memcpy + memcpy;
- else if it's nothrow relocatable, then serialize + serialize + memcpy +
memcpy + memcpy + deserialize + deserialize;
- (else if it's relocatable, can we figure out a way to do it
exception-safely??)
- else move + move-assign + move-assign + destroy.
P1144's `swap` can just say
- if it's trivially relocatable, then memcpy + memcpy + memcpy;
- else move + move-assign + move-assign + destroy.
I admit that maybe in practice you would trust the inliner to inline away
the calls to serialize/deserialize (except at -O0 of course, but maybe we
don't care about swapping things fast at -O0), so that would reduce your
`swap` to the same number of `if constexpr` branches as mine. But if you
*do* want fast swap at -O0, then yours requires one more `if constexpr`
branch than mine.
This is a very minor point, and certainly is not the major beef I have with
your definition.
> What I want to highlight is: the fallback depends on the algorithm.
> But as we (mostly) agree on what types are trivially relocatable, those
> algorithms will use the most efficient implementation in the same cases.
> The safety here comes from the (trivial) relocation concept: if only safe
> types are (trivially) relocatable, then those algorithms will also be saf=
e.
>
FWIW, I don't understand the word "safe" in that sentence. Have we given
"safe type" a formal meaning in this thread?
The undefined behaviour was about types with defaulted relocation which fit
> in one of those 4 cases. But your proposal will have the same problem her=
e:
> class [[trivially_relocatable]] list {
> /* ... */
> };
> Oups, class invariant depends on this, but type is trivially relocatable.
> This should be made UB (because you cannot prove that the class invariant
> depends on this).
>
Yes, P1144's proposed wording explicitly states
<http://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-at=
tribute>
:
> If a class type is declared with the trivially_relocatable attribute, and
the program relies on observable side-effects of relocation other than a
copy of the underlying bytes, the behavior is undefined.
(The term "relocation" as used in this quotation is formally defined in
P1144/[definitions]
<http://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-op=
eration>
..)
[...]
> Your swap is basically the same as mine. Except I can handle user-defined
> relocation.
>
Agreed. And I can handle user-defined move and destroy (as can you). So my
question for you now is, what's a situation where a type might have
user-defined "serialize/deserialize" operations, *and* some kind of
"move/destroy" operations (so that it remains swappable by the C++17
definition), but where "serialize/deserialize" is *faster* than
"move/destroy"?
That is, in the current iteration of your idea, both of us can efficiently
swap
struct One {
std::unique_ptr<int> p;
};
and both of us can inefficiently swap
struct Two {
hypothetically_relocatable::offset_ptr<int> q;
};
=E2=80=94 you would do `Two` via
serialize/serialize/memcpy/memcpy/memcpy/deserialize/deserialize, whereas I
would immediately fall all the way back to
moveconstruct/moveassign/moveassign/(trivial-destroy).
[...]
> I wish there were a memswap function. I agree codegen from
> std::swap_ranges is nasty (I didn't try). But codegen from memcpy is not
> perfect either (a third of the memory accesses could be avoided).
> The best would be memswap, but that does not exist.
>
I agree. :)
[...Switching gears now to talk about "position-independence"...]
>>
>>>
>>> Basically, when you say "relocatable", you just say "movable", and only
> trivially relocatable has a special meaning. That's not something I find
> useful.
>
But I find it useful, mainly for vector::resize (which is really just
standardizing existing practice as seen in Folly's FBVector
<https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#objec=
t-relocation>
and EASTL's deque
<https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911d05c=
85e7ba75120/include/EASTL/deque.h#L1791>
).
I would also find this serialize/deserialize mechanism useful, *if* it
could be used in the way you apparently envision for it to be used, to
"wormhole" position-independent object representations across process
boundaries or from page to page without a physical memcpy operation.
Unfortunately, as I said, position-independence is a property of a whole
region of memory; it's not a property of an individual typed object.
Consider a boost::container::vector<T, A> where A is an allocator with a
pointer type of boost::interprocess::offset_ptr<T>. What should be the
semantics of `vector::operator serialize`?
Well, if the vector's elements are definitely allocated within the *same*
interprocess shared memory segment, then `operator serialize` should be
defined as a no-op.
If the vector's elements are (possibly) allocated in a *different* shared
memory segment, or on the global heap, then `operator serialize` should not
be declared (or should be deleted).
The programmer can't possibly design `vector` to delete-or-not-delete an
operator based on the *runtime* behavior of the programmer's program!
Furthermore, you'll need to come up with a way for your scheme to work with
generic containers. Even if we decree by fiat that `vector<T,
interprocess_allocator>` *shall* have a no-op `operator serialize`, we
still need to make sure that `vector<T, some_even_weirder_allocator>` does
not have a no-op `operator serialize` =E2=80=94 otherwise we're right back =
to the
"opt-out" model that I believe I've convinced you is a non-starter (because
it would require a full code audit, costing tens of thousands of dollars
and multiple months, just in order to upgrade our compiler to C++2a). So,
how would you work with generic container code?
What I think the answer is, is: Your `operator serialize` has two valid
(non-code-audit-requiring) settings: it can be trivial, or it can be
deleted. If `operator serialize` is trivial, then it corresponds exactly to
the hypothetical `std::unbless<T>` as described here
<https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/Xj6n_0NzBgAJ=
>,
and `operator deserialize` corresponds exactly to `std::bless<T>`. If
`operator serialize` is deleted, then you lose all the benefits of
"relocation" and fall back to move+destroy.
In other words, I believe your proposal is converging onto
P1144-with-a-more-cumbersome-opt-in-mechanism. ;)
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0Kt1%3DDScDr19v1LTscsy4ehAQ%3Di-WyDJ9VYFTj=
i8ofuMw%40mail.gmail.com.
--000000000000f8b1ec05735703ff
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Aug 13, 2018 at 2:52 AM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr"><br>You seem to want all movabl=
e types to also be relocatable by saying: if a type is not trivially reloca=
table, then relocate =3D memcpy + destroy.<br>What I propose is that some t=
ypes will not be relocatable at all (more on this later). And the fallback =
is written by the user because it highly depends on where relocation is use=
d.<br>For instance, there is no way to emulate serialize+realloc+deserializ=
e with your form of fallback.<br>As I don't provide any automatic fallb=
ack at the language level, the user (might be a library writer) will need t=
o write the fallback code themselves (here: allocate+move+destroy+<wbr>deal=
locate).<br><br>So when you say "in my design, T is relocatable",=
I will now understand: "T is movable and non relocatable; serialize+m=
emcpy+deserialize could be emulated by move+destroy".<br>But I fail to=
see what you gain from this.<br></div></blockquote><div><br></div><div>Our=
definitions are converging!=C2=A0 This is good news. :)</div><div><br></di=
v><div>I am not too worried that you fail to see what we gain from P1144=
9;s definition of relocation (over yours), because vice versa I fail to see=
what we gain from your definition of relocation (over P1144's).=C2=A0 =
I think that as we plug the holes in your definition, it is quickly converg=
ing to <i>almost</i> the same thing as P1144; therefore both definitions ha=
ve just about the same advantages and disadvantages. The only thing I would=
tout as a remaining major advantage of P1144 is that it has a proposal wit=
h wording and a complete implementation on Godbolt =E2=80=94 and I will hap=
pily admit that this is purely circumstantial and does not necessarily indi=
cate that yours <i>couldn't</i> have such an implementation (now that m=
ost of the holes are plugged).</div><div><br></div><div>Meanwhile, <a href=
=3D"https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s4FWah0qC=
wAJ">over in SG14 Nicol and I have just been discussing std::bless/std::unb=
less</a> and seem to be converging on something very similar to what you an=
d I are now calling serialize/deserialize! =C2=A0(Except that this hypothet=
ical bless/unbless cannot be user-provided and must be no-ops.)</div><div><=
br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-=
color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Now about implici=
t relocation (in my sense).<br>There is no way to make std::unique_ptr impl=
icitly (trivially) relocatable, while also making NearPtr implicitly not re=
locatable.<br>I'm almost convinced that, while most types could be made=
trivially relocatable, and those not safe for that task are only a few, it=
is safer to opt-in more types, than opt-out a few types.<br>It is basicall=
y a trade-off between false positive (non-safe implicitly relocatable) and =
false negative (implicitly non-relocatable, but would be safe).<br></div></=
blockquote><div><br></div><div>I agree that it is a trade-off. And I agree =
that opt-in (such as P1144's attribute [[trivially_relocatable]]) is be=
tter than opt-out. (In fact, I strongly believe that opt-out is a non-start=
er.) =C2=A0This was one of our major points of disagreement originally, and=
I am happy to see that it appears to be resolved.</div><div><br></div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr">The rules for implicit seria=
lize/deserialize generation could be:<br>If a type has (implicitely or expl=
icitly) defaulted move constructor and destructor (or move is not provided =
and copy is defaulted), serialize/deserialize are generated<br>In all other=
cases, serialize/deserialize will not be implicitly generated, but can sti=
ll be explicitly defaulted.<br></div></blockquote><div><br></div><div>If yo=
u follow down this path, you'll reach P1144's proposed wording, exc=
ept that where P1144 <a href=3D"https://quuxplusone.github.io/draft/d1144-o=
bject-relocation.html#wording-inheritance">says</a> "...or a class typ=
e declared with the [[trivially_relocatable]] attribute," you'll s=
ay "...or a class type with a trivial `operator serialize` <i>and</i> =
a trivial `operator deserialize`."</div><div><br></div><div>Notice tha=
t I said "trivial", not just "explicitly defaulted", be=
cause I guess that the default `operator {de,}serialize` should call the `o=
perator {de,}serialize` of the base classes and members, perhaps? Or do you=
want `=3Ddefault` to <i>always</i> mean "no-op" even if some bas=
es are non-trivially relocatable?</div><div><br></div><div><br></div><div>[=
....]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-l=
eft:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>(=
snip: an example implementation of std::list with a user-provided move cons=
tructor, a user-provided destructor, a user-provided operator delocate, and=
a user-provided operator relocate)</div><div><br></div><div>Okay, so that =
would be how you'd <i>enable</i> "relocation support" for std=
::list.</div><div><br></div><div>And if you <i>didn't</i> provide any o=
perator delocate or operator relocate for std::list, then std::list would n=
ot be relocatable at all, is that right?</div></div></div></div></blockquot=
e><div><br></div></span><div>That was not my first thought, but you convinc=
ed me that the implicit generation of serialize/deserialize I had was not s=
afe.</div><div>So now yes.<br></div></div></blockquote><div><br></div><div>=
Okay, good. Hole plugged. :)</div><div><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left=
-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bord=
er-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div=
class=3D"gmail_quote"><div>Well, boost::unique_ptr has a user-provided mov=
e constructor, a user-provided destructor, and no operator delocate or oper=
ator relocate.</div><div>Therefore, by your logic, boost::unique_ptr would =
not be relocatable at all, is that right?</div></div></div></div></blockquo=
te><div><br></div></span><div>Now, yes. It doesn't lead to efficient co=
de, but at least, it is safe (like your proposal, actually).<br></div><span=
class=3D"gmail-"><div></div></span></div></blockquote><div><br></div><div>=
Okay, good. :)</div><div><br></div><div>[...]</div><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div di=
r=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bor=
der-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><di=
v class=3D"gmail_quote"><div>P1144 actually supports the generic algorithms=
vector::resize, std::swap, and std::uninitialized_relocate for <i>all</i> =
move-constructible, destructible types. These algorithms get compiled into =
memcpy exactly when it's safe to do so (by observing the "triviall=
y relocatable" concept), and fall back onto "relocate =3D move + =
destroy" in the general case.</div></div></div></div></blockquote><div=
><br></div></span><div>What do you gain from having all movable types reloc=
atable? It is never said that swap only works for relocatable types.</div><=
/div></blockquote><div><br></div><div>What you gain is fewer branches in pr=
actice. Your `swap` has to say</div><div>- if it's trivially relocatabl=
e, then memcpy + memcpy + memcpy;</div><div>- else if it's nothrow relo=
catable, then serialize + serialize + memcpy + memcpy + memcpy + deserializ=
e + deserialize;</div><div>- (else if it's relocatable, can we figure o=
ut a way to do it exception-safely??)</div><div>- else move + move-assign +=
move-assign + destroy.</div><div>P1144's `swap` can just say</div><div=
><div>- if it's trivially relocatable, then memcpy + memcpy + memcpy;</=
div><div>- else move + move-assign + move-assign + destroy.<br></div></div>=
<div><br></div><div>I admit that maybe in practice you would trust the inli=
ner to inline away the calls to serialize/deserialize (except at -O0 of cou=
rse, but maybe we don't care about swapping things fast at -O0), so tha=
t would reduce your `swap` to the same number of `if constexpr` branches as=
mine. But if you <i>do</i> want fast swap at -O0, then yours requires one =
more `if constexpr` branch than mine.</div><div><br></div><div>This is a ve=
ry minor point, and certainly is not the major beef I have with your defini=
tion.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style=
:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div> What I want to highlight is: the fallback depends on the algorithm.=
</div><div>But as we (mostly) agree on what types are trivially relocatable=
, those algorithms will use the most efficient implementation in the same c=
ases. The safety here comes from the (trivial) relocation concept: if only =
safe types are (trivially) relocatable, then those algorithms will also be =
safe.</div></div></blockquote><div><br></div><div>FWIW, I don't underst=
and the word "safe" in that sentence. Have we given "safe ty=
pe" a formal meaning in this thread?</div><div><br></div><div><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204)=
;padding-left:1ex"><div dir=3D"ltr"><div>The undefined behaviour was about =
types with defaulted relocation which fit in one of those 4 cases. But your=
proposal will have the same problem here:</div><div><div style=3D"backgrou=
nd-color:rgb(250,250,250);border:1px solid rgb(187,187,187)" class=3D"gmail=
-m_5715867662755493409prettyprint"><code class=3D"gmail-m_57158676627554934=
09prettyprint"><div class=3D"gmail-m_5715867662755493409subprettyprint"><sp=
an style=3D"color:rgb(0,0,136)" class=3D"gmail-m_5715867662755493409styled-=
by-prettify">class</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_=
5715867662755493409styled-by-prettify"> </span><span style=3D"color:rgb(102=
,102,0)" class=3D"gmail-m_5715867662755493409styled-by-prettify">[[</span><=
span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_5715867662755493409styled-=
by-prettify">trivially_relocatable</span><span style=3D"color:rgb(102,102,0=
)" class=3D"gmail-m_5715867662755493409styled-by-prettify">]]</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D"gmail-m_5715867662755493409styled-by-pre=
ttify"> list </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_5=
715867662755493409styled-by-prettify">{</span><span style=3D"color:rgb(0,0,=
0)" class=3D"gmail-m_5715867662755493409styled-by-prettify"><br>=C2=A0 </sp=
an><span style=3D"color:rgb(136,0,0)" class=3D"gmail-m_5715867662755493409s=
tyled-by-prettify">/* ... */</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_5715867662755493409styled-by-prettify"><br></span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_5715867662755493409styled-by-pre=
ttify">};</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_571586766=
2755493409styled-by-prettify"><br></span></div></code></div>Oups, class inv=
ariant depends on this, but type is trivially relocatable. This should be m=
ade UB (because you cannot prove that the class invariant depends on this).=
<br></div></div></blockquote><div><br></div><div>Yes, P1144's proposed =
wording=C2=A0<a href=3D"http://quuxplusone.github.io/draft/d1144-object-rel=
ocation.html#wording-attribute">explicitly states</a>:</div><div>>=C2=A0=
<span style=3D"color:rgb(0,0,0);font-family:sans-serif;font-size:13.3333330=
15441895px">If a class type is declared with the=C2=A0</span><code class=3D=
"gmail-highlight" style=3D"color:rgb(0,0,0);font-family:Menlo,Consolas,&quo=
t;DejaVu Sans Mono",Monaco,monospace;font-size:0.9em;break-inside:avoi=
d;padding:0.1em;border-top-left-radius:0.3em;border-top-right-radius:0.3em;=
border-bottom-right-radius:0.3em;border-bottom-left-radius:0.3em;background=
-color:rgb(245,242,240)"><span style=3D"color:rgb(0,119,170)">trivially_rel=
ocatable</span></code><span style=3D"color:rgb(0,0,0);font-family:sans-seri=
f;font-size:13.333333015441895px">=C2=A0attribute, and the program relies o=
n observable side-effects of relocation other than a copy of the underlying=
bytes, the behavior is undefined.</span></div><div><span style=3D"color:rg=
b(0,0,0);font-family:sans-serif;font-size:13.333333015441895px">(The term &=
quot;relocation" as used in this quotation is formally defined in <a h=
ref=3D"http://quuxplusone.github.io/draft/d1144-object-relocation.html#word=
ing-operation">P1144/[definitions]</a>.)</span></div><div><br></div><div><b=
r></div><div>[...]</div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-=
color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>Your swap is=
basically the same as mine. Except I can handle user-defined relocation.<b=
r></div></div></blockquote><div><br></div><div>Agreed. And I can handle use=
r-defined move and destroy (as can you).=C2=A0 So my question for you now i=
s, what's a situation where a type might have user-defined "serial=
ize/deserialize" operations, <i>and</i> some kind of "move/destro=
y" operations (so that it remains swappable by the C++17 definition), =
but where "serialize/deserialize" is <i>faster</i> than "mov=
e/destroy"?</div><div><br></div><div>That is, in the current iteration=
of your idea, both of us can efficiently swap</div><div>=C2=A0 =C2=A0 stru=
ct One {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 std::unique_ptr<int> p=
;</div><div>=C2=A0 =C2=A0 };</div><div>and both of us can inefficiently swa=
p</div><div>=C2=A0 =C2=A0 struct Two {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 hypothetically_relocatable::offset_ptr<int> q;</div><div>=C2=A0 =
=C2=A0 };</div><div>=E2=80=94 you would do `Two` via serialize/serialize/me=
mcpy/memcpy/memcpy/deserialize/deserialize, whereas I would immediately fal=
l all the way back to moveconstruct/moveassign/moveassign/(trivial-destroy)=
..</div><div><br></div><div><br></div><div>[...]</div><blockquote class=3D"g=
mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-=
left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr"><div>I wish there were a memswap function. I agree codegen from=
std::swap_ranges is nasty (I didn't try). But codegen from memcpy is n=
ot perfect either (a third of the memory accesses could be avoided).</div><=
div>The best would be memswap, but that does not exist.<br></div></div></bl=
ockquote><div><br></div><div>I agree. :)</div><div><br></div><div><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);=
padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>[...Switching gears n=
ow to talk about "position-independence"...]</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex=
"><div dir=3D"ltr"><div></div><div><br></div></div></blockquote></div></div=
></div></blockquote></span><div>Basically, when you say "relocatable&q=
uot;, you just say "movable", and only trivially relocatable has =
a special meaning. That's not something I find useful.</div></div></blo=
ckquote><div><br></div><div>But I find it useful, mainly for vector::resize=
(which is really just standardizing existing practice as seen in <a href=
=3D"https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#ob=
ject-relocation">Folly's FBVector</a> and <a href=3D"https://github.com=
/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911d05c85e7ba75120/include=
/EASTL/deque.h#L1791">EASTL's deque</a>).</div><div><br></div><div>I wo=
uld also find this serialize/deserialize mechanism useful, <i><b>if</b></i>=
it could be used in the way you apparently envision for it to be used, to =
"wormhole" position-independent object representations across pro=
cess boundaries or from page to page without a physical memcpy operation.=
=C2=A0 Unfortunately, as I said, position-independence is a property of a w=
hole region of memory; it's not a property of an individual typed objec=
t.</div><div><br></div><div>Consider a boost::container::vector<T, A>=
where A is an allocator with a pointer type of boost::interprocess::offset=
_ptr<T>.=C2=A0 What should be the semantics of `vector::operator seri=
alize`?</div><div>Well, if the vector's elements are definitely allocat=
ed within the <i>same</i> interprocess shared memory segment, then `operato=
r serialize` should be defined as a no-op.</div><div>If the vector's el=
ements are (possibly)=C2=A0allocated=C2=A0in a <i>different</i> shared memo=
ry segment, or on the global heap, then `operator serialize` should not be =
declared (or should be deleted).</div><div>The programmer can't possibl=
y design `vector` to delete-or-not-delete an operator based on the <i>runti=
me</i> behavior of the programmer's program!</div><div><br></div><div>F=
urthermore, you'll need to come up with a way for your scheme to work w=
ith generic containers. Even if we decree by fiat that `vector<T, interp=
rocess_allocator>` <i>shall</i> have a no-op `operator serialize`, we st=
ill need to make sure that `vector<T, some_even_weirder_allocator>` d=
oes not have a no-op `operator serialize` =E2=80=94 otherwise we're rig=
ht back to the "opt-out" model that I believe I've convinced =
you is a non-starter (because it would require a full code audit, costing t=
ens of thousands of dollars and multiple months, just in order to upgrade o=
ur compiler to C++2a).=C2=A0 So, how would you work with generic container =
code?</div><div><br></div><div><br></div><div>What I think the answer is, i=
s: Your `operator serialize` has two valid (non-code-audit-requiring) setti=
ngs: it can be trivial, or it can be deleted. If `operator serialize` is tr=
ivial, then it corresponds exactly to the hypothetical `std::unbless<T&g=
t;` as described <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/sg=
14/6mAbZOTdVjk/Xj6n_0NzBgAJ">here</a>, and `operator deserialize` correspon=
ds exactly to `std::bless<T>`.=C2=A0 If `operator serialize` is delet=
ed, then you lose all the benefits of "relocation" and fall back =
to move+destroy.</div><div>In other words, I believe your proposal is conve=
rging onto P1144-with-a-more-cumbersome-opt-in-mechanism. ;)</div><div><br>=
</div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0Kt1%3DDScDr19v1LTscsy4ehAQ%3Di=
-WyDJ9VYFTji8ofuMw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0Kt1%3D=
DScDr19v1LTscsy4ehAQ%3Di-WyDJ9VYFTji8ofuMw%40mail.gmail.com</a>.<br />
--000000000000f8b1ec05735703ff--
.
Author: florian.csdt@gmail.com
Date: Mon, 13 Aug 2018 15:11:09 -0700 (PDT)
Raw View
------=_Part_1699_994089350.1534198269726
Content-Type: multipart/alternative;
boundary="----=_Part_1700_1058032701.1534198269729"
------=_Part_1700_1058032701.1534198269729
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Mon, Aug 13, 2018 at 2:52 AM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>>
>> You seem to want all movable types to also be relocatable by saying: if =
a=20
>> type is not trivially relocatable, then relocate =3D memcpy + destroy.
>> What I propose is that some types will not be relocatable at all (more o=
n=20
>> this later). And the fallback is written by the user because it highly=
=20
>> depends on where relocation is used.
>> For instance, there is no way to emulate serialize+realloc+deserialize=
=20
>> with your form of fallback.
>> As I don't provide any automatic fallback at the language level, the use=
r=20
>> (might be a library writer) will need to write the fallback code themsel=
ves=20
>> (here: allocate+move+destroy+deallocate).
>>
>> So when you say "in my design, T is relocatable", I will now understand:=
=20
>> "T is movable and non relocatable; serialize+memcpy+deserialize could be=
=20
>> emulated by move+destroy".
>> But I fail to see what you gain from this.
>>
>
> Our definitions are converging! This is good news. :)
>
> I am not too worried that you fail to see what we gain from P1144's=20
> definition of relocation (over yours), because vice versa I fail to see=
=20
> what we gain from your definition of relocation (over P1144's). I think=
=20
> that as we plug the holes in your definition, it is quickly converging to=
=20
> *almost* the same thing as P1144; therefore both definitions have just=20
> about the same advantages and disadvantages. The only thing I would tout =
as=20
> a remaining major advantage of P1144 is that it has a proposal with wordi=
ng=20
> and a complete implementation on Godbolt =E2=80=94 and I will happily adm=
it that=20
> this is purely circumstantial and does not necessarily indicate that your=
s=20
> *couldn't* have such an implementation (now that most of the holes are=20
> plugged).
>
As I said quite a while ago, our two proposals are not mutually exclusive.=
=20
It is possible to modify slightly yours to let the possibility to=20
standardize mine.
The only modification really necessary would be:
template <class T> concept Relocatable =3D NothrowRelocatable<T>;
template <class T> concept NothrowRelocatable =3D TriviallyRelocatable<T>;
instead of:
template <class T> concept Relocatable =3D MoveConstructible<T> &&=20
Destructible<T>;
template <class T> concept NothrowRelocatable =3D NothrowMoveConstructible<=
T>=20
&& NothrowDestructible<T>;
All the rest would be completely forward compatible. (the attribute might=
=20
be redundant, but still compatible)
=20
>
> Meanwhile, over in SG14 Nicol and I have just been discussing=20
> std::bless/std::unbless=20
> <https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s4FWah0qCw=
AJ>=20
> and seem to be converging on something very similar to what you and I are=
=20
> now calling serialize/deserialize! (Except that this hypothetical=20
> bless/unbless cannot be user-provided and must be no-ops.)
>
>
I mostly know. One thing is, std::[un]bless<T> could be changed afterwards=
=20
to call T.[de]serialize(). This might be a good way to provide user defined=
=20
[un]bless<T>.
=20
>
> Now about implicit relocation (in my sense).
>> There is no way to make std::unique_ptr implicitly (trivially)=20
>> relocatable, while also making NearPtr implicitly not relocatable.
>> I'm almost convinced that, while most types could be made trivially=20
>> relocatable, and those not safe for that task are only a few, it is safe=
r=20
>> to opt-in more types, than opt-out a few types.
>> It is basically a trade-off between false positive (non-safe implicitly=
=20
>> relocatable) and false negative (implicitly non-relocatable, but would b=
e=20
>> safe).
>>
>
> I agree that it is a trade-off. And I agree that opt-in (such as P1144's=
=20
> attribute [[trivially_relocatable]]) is better than opt-out. (In fact, I=
=20
> strongly believe that opt-out is a non-starter.) This was one of our maj=
or=20
> points of disagreement originally, and I am happy to see that it appears =
to=20
> be resolved.
>
> =20
>
>> The rules for implicit serialize/deserialize generation could be:
>> If a type has (implicitely or explicitly) defaulted move constructor and=
=20
>> destructor (or move is not provided and copy is defaulted),=20
>> serialize/deserialize are generated
>> In all other cases, serialize/deserialize will not be implicitly=20
>> generated, but can still be explicitly defaulted.
>>
>
> If you follow down this path, you'll reach P1144's proposed wording,=20
> except that where P1144 says=20
> <https://quuxplusone.github.io/draft/d1144-object-relocation.html#wording=
-inheritance>=20
> "...or a class type declared with the [[trivially_relocatable]] attribute=
,"=20
> you'll say "...or a class type with a trivial `operator serialize` *and*=
=20
> a trivial `operator deserialize`."
>
> Notice that I said "trivial", not just "explicitly defaulted", because I=
=20
> guess that the default `operator {de,}serialize` should call the `operato=
r=20
> {de,}serialize` of the base classes and members, perhaps? Or do you want=
=20
> `=3Ddefault` to *always* mean "no-op" even if some bases are non-triviall=
y=20
> relocatable?
>
>
I want default to call operator [de]serialize of subobjects. Otherwise,=20
embedding a std::list would made the type trivially relocatable where it is=
=20
not.
=20
>
> [...]
>
>> (snip: an example implementation of std::list with a user-provided move=
=20
>>> constructor, a user-provided destructor, a user-provided operator deloc=
ate,=20
>>> and a user-provided operator relocate)
>>>
>>> Okay, so that would be how you'd *enable* "relocation support" for=20
>>> std::list.
>>>
>>> And if you *didn't* provide any operator delocate or operator relocate=
=20
>>> for std::list, then std::list would not be relocatable at all, is that=
=20
>>> right?
>>>
>>
>> That was not my first thought, but you convinced me that the implicit=20
>> generation of serialize/deserialize I had was not safe.
>> So now yes.
>>
>
> Okay, good. Hole plugged. :)
>
> Well, boost::unique_ptr has a user-provided move constructor, a=20
>>> user-provided destructor, and no operator delocate or operator relocate=
..
>>> Therefore, by your logic, boost::unique_ptr would not be relocatable at=
=20
>>> all, is that right?
>>>
>>
>> Now, yes. It doesn't lead to efficient code, but at least, it is safe=20
>> (like your proposal, actually).
>>
>
> Okay, good. :)
>
> [...]
>
>> P1144 actually supports the generic algorithms vector::resize, std::swap=
,=20
>>> and std::uninitialized_relocate for *all* move-constructible,=20
>>> destructible types. These algorithms get compiled into memcpy exactly w=
hen=20
>>> it's safe to do so (by observing the "trivially relocatable" concept), =
and=20
>>> fall back onto "relocate =3D move + destroy" in the general case.
>>>
>>
>> What do you gain from having all movable types relocatable? It is never=
=20
>> said that swap only works for relocatable types.
>>
>
> What you gain is fewer branches in practice. Your `swap` has to say
> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
> - else if it's nothrow relocatable, then serialize + serialize + memcpy +=
=20
> memcpy + memcpy + deserialize + deserialize;
> - (else if it's relocatable, can we figure out a way to do it=20
> exception-safely??)
> - else move + move-assign + move-assign + destroy.
> P1144's `swap` can just say
> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
> - else move + move-assign + move-assign + destroy.
>
First thing: why having more optional cases is bad? If there is too many=20
cases to support, it is still fine to omit some of them.
Then, you wouldn't need to have a special case for trivially relocatable as=
=20
the loop of noop would be optimized away: if it's trivial, the compiler=20
knows for sure it's a noop.
About throwing relocation, I don't know how to handle or even if it makes=
=20
sense to handle it...
=20
>
> I admit that maybe in practice you would trust the inliner to inline away=
=20
> the calls to serialize/deserialize (except at -O0 of course, but maybe we=
=20
> don't care about swapping things fast at -O0), so that would reduce your=
=20
> `swap` to the same number of `if constexpr` branches as mine. But if you=
=20
> *do* want fast swap at -O0, then yours requires one more `if constexpr`=
=20
> branch than mine.
>
> This is a very minor point, and certainly is not the major beef I have=20
> with your definition.
>
> =20
>
>> What I want to highlight is: the fallback depends on the algorithm.
>> But as we (mostly) agree on what types are trivially relocatable, those=
=20
>> algorithms will use the most efficient implementation in the same cases.=
=20
>> The safety here comes from the (trivial) relocation concept: if only saf=
e=20
>> types are (trivially) relocatable, then those algorithms will also be sa=
fe.
>>
>
> FWIW, I don't understand the word "safe" in that sentence. Have we given=
=20
> "safe type" a formal meaning in this thread?
>
>
Never mind, we agree on what is trivially relocatable, and what to do in=20
this case.
=20
>
> The undefined behaviour was about types with defaulted relocation which=
=20
>> fit in one of those 4 cases. But your proposal will have the same proble=
m=20
>> here:
>> class [[trivially_relocatable]] list {
>> /* ... */
>> };
>> Oups, class invariant depends on this, but type is trivially relocatable=
..=20
>> This should be made UB (because you cannot prove that the class invarian=
t=20
>> depends on this).
>>
>
> Yes, P1144's proposed wording explicitly states=20
> <http://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-=
attribute>
> :
> > If a class type is declared with the trivially_relocatable attribute,=
=20
> and the program relies on observable side-effects of relocation other tha=
n=20
> a copy of the underlying bytes, the behavior is undefined.
> (The term "relocation" as used in this quotation is formally defined in=
=20
> P1144/[definitions]=20
> <http://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-=
operation>
> .)
>
>
So we agree here.
=20
>
> [...]
>
>> Your swap is basically the same as mine. Except I can handle user-define=
d=20
>> relocation.
>>
>
> Agreed. And I can handle user-defined move and destroy (as can you). So=
=20
> my question for you now is, what's a situation where a type might have=20
> user-defined "serialize/deserialize" operations, *and* some kind of=20
> "move/destroy" operations (so that it remains swappable by the C++17=20
> definition), but where "serialize/deserialize" is *faster* than=20
> "move/destroy"?
>
> That is, in the current iteration of your idea, both of us can efficientl=
y=20
> swap
> struct One {
> std::unique_ptr<int> p;
> };
> and both of us can inefficiently swap
> struct Two {
> hypothetically_relocatable::offset_ptr<int> q;
> };
> =E2=80=94 you would do `Two` via=20
> serialize/serialize/memcpy/memcpy/memcpy/deserialize/deserialize, whereas=
I=20
> would immediately fall all the way back to=20
> moveconstruct/moveassign/moveassign/(trivial-destroy).
>
>
I've just made a quick exmaple in godbolt of what you can gain from=20
relocatable type that are not trivially relocatable:=20
https://godbolt.org/g/wNDeGp
=20
You can see how cleaner the relocatable is compared to the non-relocatable.
> [...]
>
>> I wish there were a memswap function. I agree codegen from=20
>> std::swap_ranges is nasty (I didn't try). But codegen from memcpy is not=
=20
>> perfect either (a third of the memory accesses could be avoided).
>> The best would be memswap, but that does not exist.
>>
>
> I agree. :)
>
>
> [...Switching gears now to talk about "position-independence"...]
>>>
>>>>
>>>> Basically, when you say "relocatable", you just say "movable", and onl=
y=20
>> trivially relocatable has a special meaning. That's not something I find=
=20
>> useful.
>>
>
> But I find it useful, mainly for vector::resize (which is really just=20
> standardizing existing practice as seen in Folly's FBVector=20
> <https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#obj=
ect-relocation>=20
> and EASTL's deque=20
> <https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911d0=
5c85e7ba75120/include/EASTL/deque.h#L1791>
> ).
>
That's exactly where I think it is not useful: vector::resize could be=20
implemented with std::realloc for relocatable types, even if relocation is=
=20
not trivial (see my godbolt implementation above).
But std::realloc cannot work with move+destroy.
=20
>
> I would also find this serialize/deserialize mechanism useful, *if* it=20
> could be used in the way you apparently envision for it to be used, to=20
> "wormhole" position-independent object representations across process=20
> boundaries or from page to page without a physical memcpy operation. =20
> Unfortunately, as I said, position-independence is a property of a whole=
=20
> region of memory; it's not a property of an individual typed object.
>
I agree for interprocess communication. But I'm not convinced if we stay=20
within the bounds of our program. std:realloc is this kind of wormhole.
=20
>
> Consider a boost::container::vector<T, A> where A is an allocator with a=
=20
> pointer type of boost::interprocess::offset_ptr<T>. What should be the=
=20
> semantics of `vector::operator serialize`?
>
It would be deleted as boost::interprocess::offset_ptr<T> (which is a=20
subobject of vector) operator [de]serialize would be deleted (by the rules=
=20
for implicit generation).
=20
> Well, if the vector's elements are definitely allocated within the *same*=
=20
> interprocess shared memory segment, then `operator serialize` should be=
=20
> defined as a no-op.
>
If you really want, then you should wrap the vector (and maybe some other=
=20
types within the same segment as you see fit) to define operator=20
[de]serialize to do just that. And ensure this wrapper is used correctly.
=20
> If the vector's elements are (possibly) allocated in a *different* shared=
=20
> memory segment, or on the global heap, then `operator serialize` should n=
ot=20
> be declared (or should be deleted).
>
Only if you want IPC, but for the realloc use case, that would be=20
completely fine.
=20
> The programmer can't possibly design `vector` to delete-or-not-delete an=
=20
> operator based on the *runtime* behavior of the programmer's program!
>
> Furthermore, you'll need to come up with a way for your scheme to work=20
> with generic containers. Even if we decree by fiat that `vector<T,=20
> interprocess_allocator>` *shall* have a no-op `operator serialize`, we=20
> still need to make sure that `vector<T, some_even_weirder_allocator>` doe=
s=20
> not have a no-op `operator serialize` =E2=80=94 otherwise we're right bac=
k to the=20
> "opt-out" model that I believe I've convinced you is a non-starter (becau=
se=20
> it would require a full code audit, costing tens of thousands of dollars=
=20
> and multiple months, just in order to upgrade our compiler to C++2a). So=
,=20
> how would you work with generic container code?
>
>
For the case of vector (and all other containers which have=20
Allocator::pointer as subobject), then the default would be fine as=20
Allocator::pointer would be by default non relocatable if it has some=20
user-defined move.
=20
>
> What I think the answer is, is: Your `operator serialize` has two valid=
=20
> (non-code-audit-requiring) settings: it can be trivial, or it can be=20
> deleted. If `operator serialize` is trivial, then it corresponds exactly =
to=20
> the hypothetical `std::unbless<T>` as described here=20
> <https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/Xj6n_0NzBg=
AJ>,=20
> and `operator deserialize` corresponds exactly to `std::bless<T>`. If=20
> `operator serialize` is deleted, then you lose all the benefits of=20
> "relocation" and fall back to move+destroy.
> In other words, I believe your proposal is converging onto=20
> P1144-with-a-more-cumbersome-opt-in-mechanism. ;)=20
>
> =E2=80=93Arthur
>
You missed a case: the type is relocatable because it "inherits"=20
relocability from its subobject, and those can be relocatable without being=
=20
trivially relocatable: std::list is an example.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/74d43767-6564-4212-9e71-30e3abc04b75%40isocpp.or=
g.
------=_Part_1700_1058032701.1534198269729
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur =
O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr">On Mon, Aug 13, 2018 at 2:52 AM, <span dir=3D"ltr"><<=
a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"RT0gPhBDD=
gAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';retu=
rn true;" onclick=3D"this.href=3D'javascript:';return true;">floria=
....@gmail.com</a>></span> wrote:<br><div><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><br>You seem to want all movable types to als=
o be relocatable by saying: if a type is not trivially relocatable, then re=
locate =3D memcpy + destroy.<br>What I propose is that some types will not =
be relocatable at all (more on this later). And the fallback is written by =
the user because it highly depends on where relocation is used.<br>For inst=
ance, there is no way to emulate serialize+realloc+deserialize with your fo=
rm of fallback.<br>As I don't provide any automatic fallback at the lan=
guage level, the user (might be a library writer) will need to write the fa=
llback code themselves (here: allocate+move+destroy+<wbr>deallocate).<br><b=
r>So when you say "in my design, T is relocatable", I will now un=
derstand: "T is movable and non relocatable; serialize+memcpy+deserial=
ize could be emulated by move+destroy".<br>But I fail to see what you =
gain from this.<br></div></blockquote><div><br></div><div>Our definitions a=
re converging!=C2=A0 This is good news. :)</div><div><br></div><div>I am no=
t too worried that you fail to see what we gain from P1144's definition=
of relocation (over yours), because vice versa I fail to see what we gain =
from your definition of relocation (over P1144's).=C2=A0 I think that a=
s we plug the holes in your definition, it is quickly converging to <i>almo=
st</i> the same thing as P1144; therefore both definitions have just about =
the same advantages and disadvantages. The only thing I would tout as a rem=
aining major advantage of P1144 is that it has a proposal with wording and =
a complete implementation on Godbolt =E2=80=94 and I will happily admit tha=
t this is purely circumstantial and does not necessarily indicate that your=
s <i>couldn't</i> have such an implementation (now that most of the hol=
es are plugged).</div></div></div></div></blockquote><div><br></div><div>As=
I said quite a while ago, our two proposals are not mutually exclusive. It=
is possible to modify slightly yours to let the possibility to standardize=
mine.</div><div>The only modification really necessary would be:</div><div=
><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187,=
187, 187); border-style: solid; border-width: 1px; overflow-wrap: break-wo=
rd;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpre=
ttyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">templat=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">concept</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Relocatable</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">NothrowReloc=
atable</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">>;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">concept</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">NothrowR=
elocatable</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">TriviallyRelocatable</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">>;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span></div></code></div>ins=
tead of:</div><div><div style=3D"background-color: rgb(250, 250, 250); bord=
er-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; overf=
low-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">template</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
<</span><span style=3D"color: #008;" class=3D"styled-by-prettify">class<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">></span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">concept</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" =
class=3D"styled-by-prettify">Relocatable</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prett=
ify">MoveConstructible</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&&</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">Destructible</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">>;</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">concept</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">NothrowRelocatable</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">NothrowMoveConstructible</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&&</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">NothrowDestructible</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n></div></code></div><br>All the rest would be completely forward compatibl=
e. (the attribute might be redundant, but still compatible)<br></div><div><=
br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>Meanwhile,=
<a href=3D"https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s=
4FWah0qCwAJ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D=
'https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s4FWah0q=
CwAJ';return true;" onclick=3D"this.href=3D'https://groups.google.c=
om/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/s4FWah0qCwAJ';return true;">over=
in SG14 Nicol and I have just been discussing std::bless/std::unbless</a> =
and seem to be converging on something very similar to what you and I are n=
ow calling serialize/deserialize! =C2=A0(Except that this hypothetical bles=
s/unbless cannot be user-provided and must be no-ops.)</div><div><br></div>=
</div></div></div></blockquote><div><br></div><div>I mostly know. One thing=
is, std::[un]bless<T> could be changed afterwards to call T.[de]seri=
alize(). This might be a good way to provide user defined [un]bless<T>=
;.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pa=
dding-left:1ex"><div dir=3D"ltr">Now about implicit relocation (in my sense=
).<br>There is no way to make std::unique_ptr implicitly (trivially) reloca=
table, while also making NearPtr implicitly not relocatable.<br>I'm alm=
ost convinced that, while most types could be made trivially relocatable, a=
nd those not safe for that task are only a few, it is safer to opt-in more =
types, than opt-out a few types.<br>It is basically a trade-off between fal=
se positive (non-safe implicitly relocatable) and false negative (implicitl=
y non-relocatable, but would be safe).<br></div></blockquote><div><br></div=
><div>I agree that it is a trade-off. And I agree that opt-in (such as P114=
4's attribute [[trivially_relocatable]]) is better than opt-out. (In fa=
ct, I strongly believe that opt-out is a non-starter.) =C2=A0This was one o=
f our major points of disagreement originally, and I am happy to see that i=
t appears to be resolved.</div><div><br></div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr">The rules for implicit serialize/deserialize generati=
on could be:<br>If a type has (implicitely or explicitly) defaulted move co=
nstructor and destructor (or move is not provided and copy is defaulted), s=
erialize/deserialize are generated<br>In all other cases, serialize/deseria=
lize will not be implicitly generated, but can still be explicitly defaulte=
d.<br></div></blockquote><div><br></div><div>If you follow down this path, =
you'll reach P1144's proposed wording, except that where P1144 <a h=
ref=3D"https://quuxplusone.github.io/draft/d1144-object-relocation.html#wor=
ding-inheritance" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.=
io%2Fdraft%2Fd1144-object-relocation.html%23wording-inheritance\x26sa\x3dD\=
x26sntz\x3d1\x26usg\x3dAFQjCNEic9fQlJSQs-EmoSqaDjDCwLI3rQ';return true;=
" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2=
Fquuxplusone.github.io%2Fdraft%2Fd1144-object-relocation.html%23wording-inh=
eritance\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEic9fQlJSQs-EmoSqaDjDCwLI3=
rQ';return true;">says</a> "...or a class type declared with the [=
[trivially_relocatable]] attribute," you'll say "...or a clas=
s type with a trivial `operator serialize` <i>and</i> a trivial `operator d=
eserialize`."</div><div><br></div><div>Notice that I said "trivia=
l", not just "explicitly defaulted", because I guess that th=
e default `operator {de,}serialize` should call the `operator {de,}serializ=
e` of the base classes and members, perhaps? Or do you want `=3Ddefault` to=
<i>always</i> mean "no-op" even if some bases are non-trivially =
relocatable?</div><div><br></div></div></div></div></blockquote><div><br></=
div><div>I want default to call operator [de]serialize of subobjects. Other=
wise, embedding a std::list would made the type trivially relocatable where=
it is not.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><b=
r></div><div>[...]</div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-=
color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>(sni=
p: an example implementation of std::list with a user-provided move constru=
ctor, a user-provided destructor, a user-provided operator delocate, and a =
user-provided operator relocate)</div><div><br></div><div>Okay, so that wou=
ld be how you'd <i>enable</i> "relocation support" for std::l=
ist.</div><div><br></div><div>And if you <i>didn't</i> provide any oper=
ator delocate or operator relocate for std::list, then std::list would not =
be relocatable at all, is that right?</div></div></div></div></blockquote><=
div><br></div></span><div>That was not my first thought, but you convinced =
me that the implicit generation of serialize/deserialize I had was not safe=
..</div><div>So now yes.<br></div></div></blockquote><div><br></div><div>Oka=
y, good. Hole plugged. :)</div><div><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-st=
yle:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"=
ltr"><span><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204=
,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div>Well, boost::unique_ptr has a user-provided move constructor, a user=
-provided destructor, and no operator delocate or operator relocate.</div><=
div>Therefore, by your logic, boost::unique_ptr would not be relocatable at=
all, is that right?</div></div></div></div></blockquote><div><br></div></s=
pan><div>Now, yes. It doesn't lead to efficient code, but at least, it =
is safe (like your proposal, actually).<br></div><span><div></div></span></=
div></blockquote><div><br></div><div>Okay, good. :)</div><div><br></div><di=
v>[...]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr"><span><blockquote class=3D"g=
mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-=
left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr"><div><div class=3D"gmail_quote"><div>P1144 actually supports th=
e generic algorithms vector::resize, std::swap, and std::uninitialized_relo=
cate for <i>all</i> move-constructible, destructible types. These algorithm=
s get compiled into memcpy exactly when it's safe to do so (by observin=
g the "trivially relocatable" concept), and fall back onto "=
relocate =3D move + destroy" in the general case.</div></div></div></d=
iv></blockquote><div><br></div></span><div>What do you gain from having all=
movable types relocatable? It is never said that swap only works for reloc=
atable types.</div></div></blockquote><div><br></div><div>What you gain is =
fewer branches in practice. Your `swap` has to say</div><div>- if it's =
trivially relocatable, then memcpy + memcpy + memcpy;</div><div>- else if i=
t's nothrow relocatable, then serialize + serialize + memcpy + memcpy +=
memcpy + deserialize + deserialize;</div><div>- (else if it's relocata=
ble, can we figure out a way to do it exception-safely??)</div><div>- else =
move + move-assign + move-assign + destroy.</div><div>P1144's `swap` ca=
n just say</div><div><div>- if it's trivially relocatable, then memcpy =
+ memcpy + memcpy;</div><div>- else move + move-assign + move-assign + dest=
roy.<br></div></div></div></div></div></blockquote><div><br></div><div>Firs=
t thing: why having more optional cases is bad? If there is too many cases =
to support, it is still fine to omit some of them.</div><div>Then, you woul=
dn't need to have a special case for trivially relocatable as the loop =
of noop would be optimized away: if it's trivial, the compiler knows fo=
r sure it's a noop.</div><div><br></div><div>About throwing relocation,=
I don't know how to handle or even if it makes sense to handle it...<b=
r></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><div><div class=3D"gmail_quote"><div><div></div></div><div><br>=
</div><div>I admit that maybe in practice you would trust the inliner to in=
line away the calls to serialize/deserialize (except at -O0 of course, but =
maybe we don't care about swapping things fast at -O0), so that would r=
educe your `swap` to the same number of `if constexpr` branches as mine. Bu=
t if you <i>do</i> want fast swap at -O0, then yours requires one more `if =
constexpr` branch than mine.</div><div><br></div><div>This is a very minor =
point, and certainly is not the major beef I have with your definition.</di=
v><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>=
What I want to highlight is: the fallback depends on the algorithm.</div><=
div>But as we (mostly) agree on what types are trivially relocatable, those=
algorithms will use the most efficient implementation in the same cases. T=
he safety here comes from the (trivial) relocation concept: if only safe ty=
pes are (trivially) relocatable, then those algorithms will also be safe.</=
div></div></blockquote><div><br></div><div>FWIW, I don't understand the=
word "safe" in that sentence. Have we given "safe type"=
; a formal meaning in this thread?</div><div><br></div></div></div></div></=
blockquote><div><br></div><div>Never mind, we agree on what is trivially re=
locatable, and what to do in this case.<br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div></div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>=
The undefined behaviour was about types with defaulted relocation which fit=
in one of those 4 cases. But your proposal will have the same problem here=
:</div><div><div style=3D"background-color:rgb(250,250,250);border:1px soli=
d rgb(187,187,187)"><code><div><span style=3D"color:rgb(0,0,136)">class</sp=
an><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,10=
2,0)">[[</span><span style=3D"color:rgb(0,0,0)">trivially_relocatable</span=
><span style=3D"color:rgb(102,102,0)">]]</span><span style=3D"color:rgb(0,0=
,0)"> list </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(136,0,0)">=
/* ... */</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"=
color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br></span>=
</div></code></div>Oups, class invariant depends on this, but type is trivi=
ally relocatable. This should be made UB (because you cannot prove that the=
class invariant depends on this).<br></div></div></blockquote><div><br></d=
iv><div>Yes, P1144's proposed wording=C2=A0<a href=3D"http://quuxpluson=
e.github.io/draft/d1144-object-relocation.html#wording-attribute" target=3D=
"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google=
..com/url?q\x3dhttp%3A%2F%2Fquuxplusone.github.io%2Fdraft%2Fd1144-object-rel=
ocation.html%23wording-attribute\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFP=
Hn-IEglkaDH9-WFp6aai6WBF8g';return true;" onclick=3D"this.href=3D'h=
ttp://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxplusone.github.io%2Fdraft%2F=
d1144-object-relocation.html%23wording-attribute\x26sa\x3dD\x26sntz\x3d1\x2=
6usg\x3dAFQjCNFPHn-IEglkaDH9-WFp6aai6WBF8g';return true;">explicitly st=
ates</a>:</div><div>>=C2=A0<span style=3D"color:rgb(0,0,0);font-family:s=
ans-serif;font-size:13.333333015441895px">If a class type is declared with =
the=C2=A0</span><code style=3D"color:rgb(0,0,0);font-family:Menlo,Consolas,=
"DejaVu Sans Mono",Monaco,monospace;font-size:0.9em;padding:0.1em=
;border-top-left-radius:0.3em;border-top-right-radius:0.3em;border-bottom-r=
ight-radius:0.3em;border-bottom-left-radius:0.3em;background-color:rgb(245,=
242,240)"><span style=3D"color:rgb(0,119,170)">trivially_relocatable</span>=
</code><span style=3D"color:rgb(0,0,0);font-family:sans-serif;font-size:13.=
333333015441895px">=C2=A0<wbr>attribute, and the program relies on observab=
le side-effects of relocation other than a copy of the underlying bytes, th=
e behavior is undefined.</span></div><div><span style=3D"color:rgb(0,0,0);f=
ont-family:sans-serif;font-size:13.333333015441895px">(The term "reloc=
ation" as used in this quotation is formally defined in <a href=3D"htt=
p://quuxplusone.github.io/draft/d1144-object-relocation.html#wording-operat=
ion" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'htt=
p://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxplusone.github.io%2Fdraft%2Fd1=
144-object-relocation.html%23wording-operation\x26sa\x3dD\x26sntz\x3d1\x26u=
sg\x3dAFQjCNFrYQMa6Tgk3bQCsSqo3jufP4D6qQ';return true;" onclick=3D"this=
..href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fquuxplusone.github=
..io%2Fdraft%2Fd1144-object-relocation.html%23wording-operation\x26sa\x3dD\x=
26sntz\x3d1\x26usg\x3dAFQjCNFrYQMa6Tgk3bQCsSqo3jufP4D6qQ';return true;"=
>P1144/[definitions]</a>.)</span></div><div><br></div></div></div></div></b=
lockquote><div><br></div><div>So we agree here.<br></div><div>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><div></div><div><br></div><div>[...]</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex=
"><div dir=3D"ltr"><div>Your swap is basically the same as mine. Except I c=
an handle user-defined relocation.<br></div></div></blockquote><div><br></d=
iv><div>Agreed. And I can handle user-defined move and destroy (as can you)=
..=C2=A0 So my question for you now is, what's a situation where a type =
might have user-defined "serialize/deserialize" operations, <i>an=
d</i> some kind of "move/destroy" operations (so that it remains =
swappable by the C++17 definition), but where "serialize/deserialize&q=
uot; is <i>faster</i> than "move/destroy"?</div><div><br></div><d=
iv>That is, in the current iteration of your idea, both of us can efficient=
ly swap</div><div>=C2=A0 =C2=A0 struct One {</div><div>=C2=A0 =C2=A0 =C2=A0=
=C2=A0 std::unique_ptr<int> p;</div><div>=C2=A0 =C2=A0 };</div><div>=
and both of us can inefficiently swap</div><div>=C2=A0 =C2=A0 struct Two {<=
/div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 hypothetically_relocatable::<wbr>offs=
et_ptr<int> q;</div><div>=C2=A0 =C2=A0 };</div><div>=E2=80=94 you wou=
ld do `Two` via serialize/serialize/memcpy/<wbr>memcpy/memcpy/deserialize/<=
wbr>deserialize, whereas I would immediately fall all the way back to movec=
onstruct/moveassign/<wbr>moveassign/(trivial-destroy).</div><div><br></div>=
</div></div></div></blockquote><div><br></div><div>I've just made a qui=
ck exmaple in godbolt of what you can gain from relocatable type that are n=
ot trivially relocatable: <a href=3D"https://godbolt.org/g/wNDeGp">https://=
godbolt.org/g/wNDeGp</a><br></div><div>=C2=A0</div><div>You can see how cle=
aner the relocatable is compared to the non-relocatable.</div><div><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div></div><div><br></div><div>[...]</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr"><div>I wish there were a memswap function. I agree co=
degen from std::swap_ranges is nasty (I didn't try). But codegen from m=
emcpy is not perfect either (a third of the memory accesses could be avoide=
d).</div><div>The best would be memswap, but that does not exist.<br></div>=
</div></blockquote><div><br></div><div>I agree. :)</div><div><br></div><div=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204=
,204,204);padding-left:1ex"><div dir=3D"ltr"><span><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div di=
r=3D"ltr"><div><div class=3D"gmail_quote"><div>[...Switching gears now to t=
alk about "position-independence"...]</div><blockquote class=3D"g=
mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-=
left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr"><div></div><div><br></div></div></blockquote></div></div></div>=
</blockquote></span><div>Basically, when you say "relocatable", y=
ou just say "movable", and only trivially relocatable has a speci=
al meaning. That's not something I find useful.</div></div></blockquote=
><div><br></div><div>But I find it useful, mainly for vector::resize (which=
is really just standardizing existing practice as seen in <a href=3D"https=
://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relo=
cation" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Ffacebook%2Ffolly=
%2Fblob%2Fmaster%2Ffolly%2Fdocs%2FFBVector.md%23object-relocation\x26sa\x3d=
D\x26sntz\x3d1\x26usg\x3dAFQjCNFvC1J0BKMgS8e1uQcZOZ70ZQw6PQ';return tru=
e;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F=
%2Fgithub.com%2Ffacebook%2Ffolly%2Fblob%2Fmaster%2Ffolly%2Fdocs%2FFBVector.=
md%23object-relocation\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFvC1J0BKMgS8=
e1uQcZOZ70ZQw6PQ';return true;">Folly's FBVector</a> and <a href=3D=
"https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911d05c=
85e7ba75120/include/EASTL/deque.h#L1791" target=3D"_blank" rel=3D"nofollow"=
onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2=
F%2Fgithub.com%2Felectronicarts%2FEASTL%2Fblob%2F84127fd4ac234b24a40ea7911d=
05c85e7ba75120%2Finclude%2FEASTL%2Fdeque.h%23L1791\x26sa\x3dD\x26sntz\x3d1\=
x26usg\x3dAFQjCNFR_YPCDKbNkT7I2UbB3wcAK2oGTw';return true;" onclick=3D"=
this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2=
Felectronicarts%2FEASTL%2Fblob%2F84127fd4ac234b24a40ea7911d05c85e7ba75120%2=
Finclude%2FEASTL%2Fdeque.h%23L1791\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCN=
FR_YPCDKbNkT7I2UbB3wcAK2oGTw';return true;">EASTL's deque</a>).</di=
v></div></div></div></blockquote><div><br></div><div>That's exactly whe=
re I think it is not useful: vector::resize could be implemented with std::=
realloc for relocatable types, even if relocation is not trivial (see my go=
dbolt implementation above).</div><div>But std::realloc cannot work with mo=
ve+destroy.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><di=
v>I would also find this serialize/deserialize mechanism useful, <i><b>if</=
b></i> it could be used in the way you apparently envision for it to be use=
d, to "wormhole" position-independent object representations acro=
ss process boundaries or from page to page without a physical memcpy operat=
ion.=C2=A0 Unfortunately, as I said, position-independence is a property of=
a whole region of memory; it's not a property of an individual typed o=
bject.</div></div></div></div></blockquote><div><br></div><div>I agree for =
interprocess communication. But I'm not convinced if we stay within the=
bounds of our program. std:realloc is this kind of wormhole.</div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
><div class=3D"gmail_quote"><div><br></div><div>Consider a boost::container=
::vector<T, A> where A is an allocator with a pointer type of boost::=
interprocess::offset_<wbr>ptr<T>.=C2=A0 What should be the semantics =
of `vector::operator serialize`?</div></div></div></div></blockquote><div><=
br></div><div>It would be deleted as boost::interprocess::offset_ptr<T&g=
t; (which is a subobject of vector) operator [de]serialize would be deleted=
(by the rules for implicit generation).<br></div><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gm=
ail_quote"><div>Well, if the vector's elements are definitely allocated=
within the <i>same</i> interprocess shared memory segment, then `operator =
serialize` should be defined as a no-op.</div></div></div></div></blockquot=
e><div><br></div><div>If you really want, then you should wrap the vector (=
and maybe some other types within the same segment as you see fit) to defin=
e operator [de]serialize to do just that. And ensure this wrapper is used c=
orrectly.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>If the vector&#=
39;s elements are (possibly)=C2=A0allocated=C2=A0in a <i>different</i> shar=
ed memory segment, or on the global heap, then `operator serialize` should =
not be declared (or should be deleted).</div></div></div></div></blockquote=
><div><br></div><div>Only if you want IPC, but for the realloc use case, th=
at would be completely fine.<br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><=
div>The programmer can't possibly design `vector` to delete-or-not-dele=
te an operator based on the <i>runtime</i> behavior of the programmer's=
program!</div><div><br></div><div>Furthermore, you'll need to come up =
with a way for your scheme to work with generic containers. Even if we decr=
ee by fiat that `vector<T, interprocess_allocator>` <i>shall</i> have=
a no-op `operator serialize`, we still need to make sure that `vector<T=
, some_even_weirder_allocator>` does not have a no-op `operator serializ=
e` =E2=80=94 otherwise we're right back to the "opt-out" mode=
l that I believe I've convinced you is a non-starter (because it would =
require a full code audit, costing tens of thousands of dollars and multipl=
e months, just in order to upgrade our compiler to C++2a).=C2=A0 So, how wo=
uld you work with generic container code?</div><div><br></div></div></div><=
/div></blockquote><div><br></div><div>For the case of vector (and all other=
containers which have Allocator::pointer as subobject), then the default w=
ould be fine as Allocator::pointer would be by default non relocatable if i=
t has some user-defined move.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div></div><div><br></div><div>What I think the answer is, is: Your `oper=
ator serialize` has two valid (non-code-audit-requiring) settings: it can b=
e trivial, or it can be deleted. If `operator serialize` is trivial, then i=
t corresponds exactly to the hypothetical `std::unbless<T>` as descri=
bed <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVj=
k/Xj6n_0NzBgAJ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'https://groups.google.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/Xj6n_=
0NzBgAJ';return true;" onclick=3D"this.href=3D'https://groups.googl=
e.com/a/isocpp.org/d/msg/sg14/6mAbZOTdVjk/Xj6n_0NzBgAJ';return true;">h=
ere</a>, and `operator deserialize` corresponds exactly to `std::bless<T=
>`.=C2=A0 If `operator serialize` is deleted, then you lose all the bene=
fits of "relocation" and fall back to move+destroy.</div><div>In =
other words, I believe your proposal is converging onto P1144-with-a-more-c=
umbersome-<wbr>opt-in-mechanism. ;) <br></div></div></div></div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div c=
lass=3D"gmail_quote"><div><br></div><div>=E2=80=93Arthur</div></div></div><=
/div></blockquote><div><br></div><div>You missed a case: the type is reloca=
table because it "inherits" relocability from its subobject, and =
those can be relocatable without being trivially relocatable: std::list is =
an example.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/74d43767-6564-4212-9e71-30e3abc04b75%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/74d43767-6564-4212-9e71-30e3abc04b75=
%40isocpp.org</a>.<br />
------=_Part_1700_1058032701.1534198269729--
------=_Part_1699_994089350.1534198269726--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Mon, 13 Aug 2018 16:37:15 -0700
Raw View
--000000000000db01e20573599222
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Mon, Aug 13, 2018 at 3:11 PM, <florian.csdt@gmail.com> wrote:
> Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>
>> On Mon, Aug 13, 2018 at 2:52 AM, <floria...@gmail.com> wrote:
>>
>>>
>>> You seem to want all movable types to also be relocatable by saying: if
>>> a type is not trivially relocatable, then relocate =3D memcpy + destroy=
..
>>> What I propose is that some types will not be relocatable at all (more
>>> on this later). And the fallback is written by the user because it high=
ly
>>> depends on where relocation is used.
>>> For instance, there is no way to emulate serialize+realloc+deserialize
>>> with your form of fallback.
>>> As I don't provide any automatic fallback at the language level, the
>>> user (might be a library writer) will need to write the fallback code
>>> themselves (here: allocate+move+destroy+deallocate).
>>>
>>> So when you say "in my design, T is relocatable", I will now understand=
:
>>> "T is movable and non relocatable; serialize+memcpy+deserialize could b=
e
>>> emulated by move+destroy".
>>> But I fail to see what you gain from this.
>>>
>>
>> Our definitions are converging! This is good news. :)
>>
>> I am not too worried that you fail to see what we gain from P1144's
>> definition of relocation (over yours), because vice versa I fail to see
>> what we gain from your definition of relocation (over P1144's). I think
>> that as we plug the holes in your definition, it is quickly converging t=
o
>> *almost* the same thing as P1144; therefore both definitions have just
>> about the same advantages and disadvantages. The only thing I would tout=
as
>> a remaining major advantage of P1144 is that it has a proposal with word=
ing
>> and a complete implementation on Godbolt =E2=80=94 and I will happily ad=
mit that
>> this is purely circumstantial and does not necessarily indicate that you=
rs
>> *couldn't* have such an implementation (now that most of the holes are
>> plugged).
>>
>
> As I said quite a while ago, our two proposals are not mutually exclusive=
..
> It is possible to modify slightly yours to let the possibility to
> standardize mine.
> The only modification really necessary would be:
> template <class T> concept Relocatable =3D NothrowRelocatable<T>;
> template <class T> concept NothrowRelocatable =3D TriviallyRelocatable<T>=
;
> instead of:
> template <class T> concept Relocatable =3D MoveConstructible<T> &&
> Destructible<T>;
> template <class T> concept NothrowRelocatable =3D NothrowMoveConstructibl=
e<T
> > && NothrowDestructible<T>;
>
I don't quite see what the former two lines are doing. You want things to
be Relocatable iff they are TriviallyRelocatable? But what about things
that are "relocatable but non-trivially so"? In P1144, that would be
anything with a user-defined move-ctor and dtor; in your scheme, that would
be anything with a user-defined `serialize` and `deserialize`.
I think pursuing this line might confuse both of us even more, so I'd be
happy to drop it. :P
> The rules for implicit serialize/deserialize generation could be:
>>> If a type has (implicitely or explicitly) defaulted move constructor an=
d
>>> destructor (or move is not provided and copy is defaulted),
>>> serialize/deserialize are generated
>>> In all other cases, serialize/deserialize will not be implicitly
>>> generated, but can still be explicitly defaulted.
>>>
>>
>> If you follow down this path, you'll reach P1144's proposed wording,
>> except that where P1144 says
>> <https://quuxplusone.github.io/draft/d1144-object-relocation.html#wordin=
g-inheritance>
>> "...or a class type declared with the [[trivially_relocatable]] attribut=
e,"
>> you'll say "...or a class type with a trivial `operator serialize` *and*
>> a trivial `operator deserialize`."
>>
>> Notice that I said "trivial", not just "explicitly defaulted", because I
>> guess that the default `operator {de,}serialize` should call the `operat=
or
>> {de,}serialize` of the base classes and members, perhaps? Or do you want
>> `=3Ddefault` to *always* mean "no-op" even if some bases are non-trivial=
ly
>> relocatable?
>>
>
> I want default to call operator [de]serialize of subobjects. Otherwise,
> embedding a std::list would made the type trivially relocatable where it =
is
> not.
>
And later in your message, you write:
> You missed a case: the type is relocatable because it "inherits"
relocability from its subobject,
> and those can be relocatable without being trivially relocatable:
std::list is an example.
Good point. Agreed.
But does that conflict with your desire to have `operator serialize() =3D
default;` be the opt-in mechanism?
Two messages ago, I understood you as wanting the following `One` to be
trivially relocatable.
struct One {
std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially
relocatable, or perhaps nonrelocatable
offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or perhaps
nonrelocatable
// Warrant that "One" happens to be trivially relocatable for our
purposes, even though its individual members are not trivially relocatable
operator serialize() =3D default;
operator deserialize() =3D default;
};
But now, as I understand your latest message, you want this `Two` to be
*non*-trivially relocatable.
struct Two {
std::list<int> m; // nontrivially relocatable
// Ask the compiler to generate recursive definitions for these, i.e.,
they'll end up with non-trivial, non-noop definitions
operator serialize() =3D default;
operator deserialize() =3D default;
};
How will the compiler tell the difference?
I suppose a valid answer would be that my `One` is not quite right; that it
should be
struct Three {
std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially
relocatable, or perhaps nonrelocatable
offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or perhaps
nonrelocatable
// Warrant that "Three" happens to be trivially relocatable for our
purposes, even though its individual members are not trivially relocatable
operator serialize() {}
operator deserialize() {}
};
Here the core language cannot possibly tell that `operator serialize` and
`operator deserialize` are *trivial*, because they are user-provided; but
we can throw ourselves on the mercy of a sufficiently smart inliner and
expect that at least the compiler will generate efficient code for the
(technically non-trivial) operation.
In other words, it sounds like your scheme is moving away from the idea of
"trivial"-anything-optimizing-into-memcpy at the library level, and toward
the idea that "serialize + memcpy + deserialize" should be the *fundamental
mechanism* used by the library to relocate anything (unless it's not
relocatable, in which case the library should fall back to move + destroy).
[...]
> What do you gain from having all movable types relocatable? It is never
>>> said that swap only works for relocatable types.
>>>
>>
>> What you gain is fewer branches in practice. Your `swap` has to say
>> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
>> - else if it's nothrow relocatable, then serialize + serialize + memcpy =
+
>> memcpy + memcpy + deserialize + deserialize;
>> - (else if it's relocatable, can we figure out a way to do it
>> exception-safely??)
>> - else move + move-assign + move-assign + destroy.
>> P1144's `swap` can just say
>> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
>> - else move + move-assign + move-assign + destroy.
>>
>
> First thing: why having more optional cases is bad? If there is too many
> cases to support, it is still fine to omit some of them.
> Then, you wouldn't need to have a special case for trivially relocatable
> as the loop of noop would be optimized away: if it's trivial, the compile=
r
> knows for sure it's a noop.
>
If you omit some of the cases, then your library has poor Quality of
Implementation and your competitors make fun of you.
If you don't omit any of the cases, then your library takes longer to
implement and test and debug.
One way out of this dilemma is to make the optimal specification have *fewe=
r
cases to begin with*.
[...]
>>
> Your swap is basically the same as mine. Except I can handle user-defined
>>> relocation.
>>>
>>
>> Agreed. And I can handle user-defined move and destroy (as can you). So
>> my question for you now is, what's a situation where a type might have
>> user-defined "serialize/deserialize" operations, *and* some kind of
>> "move/destroy" operations (so that it remains swappable by the C++17
>> definition), but where "serialize/deserialize" is *faster* than
>> "move/destroy"?
>>
>> That is, in the current iteration of your idea, both of us can
>> efficiently swap
>> struct One {
>> std::unique_ptr<int> p;
>> };
>> and both of us can inefficiently swap
>> struct Two {
>> hypothetically_relocatable::offset_ptr<int> q;
>> };
>> =E2=80=94 you would do `Two` via serialize/serialize/memcpy/mem
>> cpy/memcpy/deserialize/deserialize, whereas I would immediately fall all
>> the way back to moveconstruct/moveassign/moveassign/(trivial-destroy).
>>
>
> I've just made a quick exmaple in godbolt of what you can gain from
> relocatable type that are not trivially relocatable:
> https://godbolt.org/g/wNDeGp
>
> You can see how cleaner the relocatable is compared to the non-relocatabl=
e.
>
Here's a reduced Godbolt <https://godbolt.org/g/FMo62c> with the two swap
functions side-by-side. Indeed, that is very cool!
I admit that, as far as I know, P1144 cannot do that for std::list.
Basically, when you say "relocatable", you just say "movable", and only
>>> trivially relocatable has a special meaning. That's not something I fin=
d
>>> useful.
>>>
>>
>> But I find it useful, mainly for vector::resize (which is really just
>> standardizing existing practice as seen in Folly's FBVector
>> <https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#ob=
ject-relocation>
>> and EASTL's deque
>> <https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911d=
05c85e7ba75120/include/EASTL/deque.h#L1791>
>> ).
>>
>
> That's exactly where I think it is not useful: vector::resize could be
> implemented with std::realloc for relocatable types, even if relocation i=
s
> not trivial (see my godbolt implementation above).
> But std::realloc cannot work with move+destroy.
>
Right. If our goal is to reallocate an array of `std::list` objects,
then your scheme can use "serialize in a loop + realloc + deserialize in a
loop."
P1144 cannot possibly use realloc in that scenario, and must fall back to
"malloc + (move+destroy) in a loop + free."
This applies to `std::list` because it is non-trivially relocatable. To
reallocate an array of `std::deque` objects, your scheme would use
"serialize in a loop + realloc + deserialize in a loop" and mine would use
"(unbless?) + realloc + (bless?)," i.e., we'd be equivalent.
(Pedantic note that in practice, `*std*::vector` cannot possibly use
`realloc` because it must behave as-if it were using
`allocator_traits::allocate` and `allocator_traits::deallocate`. To
actually make it use `realloc` you'd first have to make an allocator type
that used `malloc` and `free` instead of `operator new` and `operator
delete`, and then you'd have to teach `std::vector` about that allocator
type as a special case. But I can certainly imagine a nonstd::vector =E2=80=
=94
either non-allocator-aware, or allocator-aware using a richer allocator
model than the standard C++17 allocator model =E2=80=94 that would want the=
ability
to do this optimization. Also, even if we don't permit `realloc`, your
scheme still does
allocate + serialize in a loop + memcpy + deserialize in a loop +
deallocate
whereas P1144 does
allocate + (move+destroy) in a loop + deallocate
..)
I would also find this serialize/deserialize mechanism useful, *if* it
>> could be used in the way you apparently envision for it to be used, to
>> "wormhole" position-independent object representations across process
>> boundaries or from page to page without a physical memcpy operation.
>> Unfortunately, as I said, position-independence is a property of a whole
>> region of memory; it's not a property of an individual typed object.
>>
>
> I agree for interprocess communication. But I'm not convinced if we stay
> within the bounds of our program. std:realloc is this kind of wormhole.
>
Agreed. So "reallocate an array of `std::list` objects" becomes the killer
app for the serialize+deserialize approach? And we haven't made any
particular progress on the interprocess case?
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0Kfb8c6VafR7xCXQc3Mvi_HmCJJwvHBdiRRjJcomok=
p%3Dg%40mail.gmail.com.
--000000000000db01e20573599222
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Aug 13, 2018 at 3:11 PM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<div class=3D"gmail_extra"><div class=3D"gmail_q=
uote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,=
204);padding-left:1ex"><div dir=3D"ltr">Le lundi 13 ao=C3=BBt 2018 22:34:12=
UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span class=3D"gmail-"><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding=
-left:1ex"><div dir=3D"ltr">On Mon, Aug 13, 2018 at 2:52 AM, <span dir=3D"=
ltr"><<a rel=3D"nofollow">floria...@gmail.com</a>></span> wrote:<br><=
div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;borde=
r-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><br>You se=
em to want all movable types to also be relocatable by saying: if a type is=
not trivially relocatable, then relocate =3D memcpy + destroy.<br>What I p=
ropose is that some types will not be relocatable at all (more on this late=
r). And the fallback is written by the user because it highly depends on wh=
ere relocation is used.<br>For instance, there is no way to emulate seriali=
ze+realloc+deserialize with your form of fallback.<br>As I don't provid=
e any automatic fallback at the language level, the user (might be a librar=
y writer) will need to write the fallback code themselves (here: allocate+m=
ove+destroy+dealloca<wbr>te).<br><br>So when you say "in my design, T =
is relocatable", I will now understand: "T is movable and non rel=
ocatable; serialize+memcpy+deserialize could be emulated by move+destroy&qu=
ot;.<br>But I fail to see what you gain from this.<br></div></blockquote><d=
iv><br></div><div>Our definitions are converging!=C2=A0 This is good news. =
:)</div><div><br></div><div>I am not too worried that you fail to see what =
we gain from P1144's definition of relocation (over yours), because vic=
e versa I fail to see what we gain from your definition of relocation (over=
P1144's).=C2=A0 I think that as we plug the holes in your definition, =
it is quickly converging to <i>almost</i> the same thing as P1144; therefor=
e both definitions have just about the same advantages and disadvantages. T=
he only thing I would tout as a remaining major advantage of P1144 is that =
it has a proposal with wording and a complete implementation on Godbolt =E2=
=80=94 and I will happily admit that this is purely circumstantial and does=
not necessarily indicate that yours <i>couldn't</i> have such an imple=
mentation (now that most of the holes are plugged).</div></div></div></div>=
</blockquote><div><br></div></span><div>As I said quite a while ago, our tw=
o proposals are not mutually exclusive. It is possible to modify slightly y=
ours to let the possibility to standardize mine.</div><div>The only modific=
ation really necessary would be:</div><div><div style=3D"background-color:r=
gb(250,250,250);border:1px solid rgb(187,187,187)" class=3D"gmail-m_-231377=
4302215552814prettyprint"><code class=3D"gmail-m_-2313774302215552814pretty=
print"><div class=3D"gmail-m_-2313774302215552814subprettyprint"><span styl=
e=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302215552814styled-by-pre=
ttify">template</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-23=
13774302215552814styled-by-prettify"> </span><span style=3D"color:rgb(102,1=
02,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"><</span>=
<span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302215552814sty=
led-by-prettify">class</span><span style=3D"color:rgb(0,0,0)" class=3D"gmai=
l-m_-2313774302215552814styled-by-prettify"> T</span><span style=3D"color:r=
gb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">>=
;</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552=
814styled-by-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"=
gmail-m_-2313774302215552814styled-by-prettify">concept</span><span style=
=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-pretti=
fy"> </span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-m_-23137743=
02215552814styled-by-prettify">Relocatable</span><span style=3D"color:rgb(0=
,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </span><sp=
an style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styl=
ed-by-prettify">=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m=
_-2313774302215552814styled-by-prettify"> </span><span style=3D"color:rgb(1=
02,0,102)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">Nothrow=
Relocatable</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-23=
13774302215552814styled-by-prettify"><</span><span style=3D"color:rgb(0,=
0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">T</span><spa=
n style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814style=
d-by-prettify">>;</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-=
m_-2313774302215552814styled-by-prettify"><br></span><span style=3D"color:r=
gb(0,0,136)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">templ=
ate</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-23137743022155=
52814styled-by-prettify"> </span><span style=3D"color:rgb(102,102,0)" class=
=3D"gmail-m_-2313774302215552814styled-by-prettify"><</span><span style=
=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302215552814styled-by-pret=
tify">class</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-231377=
4302215552814styled-by-prettify"> T</span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">></span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-b=
y-prettify"> </span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-23=
13774302215552814styled-by-prettify">concept</span><span style=3D"color:rgb=
(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </span><=
span style=3D"color:rgb(102,0,102)" class=3D"gmail-m_-2313774302215552814st=
yled-by-prettify">NothrowRelocatable</span><span style=3D"color:rgb(0,0,0)"=
class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </span><span sty=
le=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by-=
prettify">=3D</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313=
774302215552814styled-by-prettify"> </span><span style=3D"color:rgb(102,0,1=
02)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">TriviallyRelo=
catable</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-231377=
4302215552814styled-by-prettify"><</span><span style=3D"color:rgb(0,0,0)=
" class=3D"gmail-m_-2313774302215552814styled-by-prettify">T</span><span st=
yle=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by=
-prettify">>;</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2=
313774302215552814styled-by-prettify"><br></span></div></code></div>instead=
of:</div><div><div style=3D"background-color:rgb(250,250,250);border:1px s=
olid rgb(187,187,187)" class=3D"gmail-m_-2313774302215552814prettyprint"><c=
ode class=3D"gmail-m_-2313774302215552814prettyprint"><div class=3D"gmail-m=
_-2313774302215552814subprettyprint"><span style=3D"color:rgb(0,0,136)" cla=
ss=3D"gmail-m_-2313774302215552814styled-by-prettify">template</span><span =
style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-p=
rettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-231=
3774302215552814styled-by-prettify"><</span><span style=3D"color:rgb(0,0=
,136)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">class</span=
><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styl=
ed-by-prettify"> T</span><span style=3D"color:rgb(102,102,0)" class=3D"gmai=
l-m_-2313774302215552814styled-by-prettify">></span><span style=3D"color=
:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </sp=
an><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302215552814=
styled-by-prettify">concept</span><span style=3D"color:rgb(0,0,0)" class=3D=
"gmail-m_-2313774302215552814styled-by-prettify"> </span><span style=3D"col=
or:rgb(102,0,102)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"=
>Relocatable</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-23137=
74302215552814styled-by-prettify"> </span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">=3D</span><spa=
n style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by=
-prettify"> </span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-m_-2=
313774302215552814styled-by-prettify">MoveConstructible</span><span style=
=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by-pr=
ettify"><</span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-23137=
74302215552814styled-by-prettify">T</span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">></span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-b=
y-prettify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-=
2313774302215552814styled-by-prettify">&&</span><span style=3D"colo=
r:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </s=
pan><span style=3D"color:rgb(102,0,102)" class=3D"gmail-m_-2313774302215552=
814styled-by-prettify">Destructible</span><span style=3D"color:rgb(102,102,=
0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"><</span><sp=
an style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-b=
y-prettify">T</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-=
2313774302215552814styled-by-prettify">>;</span><span style=3D"color:rgb=
(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"><br></spa=
n><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302215552814s=
tyled-by-prettify">template</span><span style=3D"color:rgb(0,0,0)" class=3D=
"gmail-m_-2313774302215552814styled-by-prettify"> </span><span style=3D"col=
or:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"=
><</span><span style=3D"color:rgb(0,0,136)" class=3D"gmail-m_-2313774302=
215552814styled-by-prettify">class</span><span style=3D"color:rgb(0,0,0)" c=
lass=3D"gmail-m_-2313774302215552814styled-by-prettify"> T</span><span styl=
e=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styled-by-p=
rettify">></span><span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313=
774302215552814styled-by-prettify"> </span><span style=3D"color:rgb(0,0,136=
)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">concept</span><=
span style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled=
-by-prettify"> </span><span style=3D"color:rgb(102,0,102)" class=3D"gmail-m=
_-2313774302215552814styled-by-prettify">NothrowRelocatable</span><span sty=
le=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-pret=
tify"> </span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-231377=
4302215552814styled-by-prettify">=3D</span><span style=3D"color:rgb(0,0,0)"=
class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </span><span sty=
le=3D"color:rgb(102,0,102)" class=3D"gmail-m_-2313774302215552814styled-by-=
prettify">NothrowMoveConstructible</span><span style=3D"color:rgb(102,102,0=
)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"><</span><spa=
n style=3D"color:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by=
-prettify">T</span><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2=
313774302215552814styled-by-prettify">></span><span style=3D"color:rgb(0=
,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify"> </span><sp=
an style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552814styl=
ed-by-prettify">&&</span><span style=3D"color:rgb(0,0,0)" class=3D"=
gmail-m_-2313774302215552814styled-by-prettify"> </span><span style=3D"colo=
r:rgb(102,0,102)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">=
NothrowDestructible</span><span style=3D"color:rgb(102,102,0)" class=3D"gma=
il-m_-2313774302215552814styled-by-prettify"><</span><span style=3D"colo=
r:rgb(0,0,0)" class=3D"gmail-m_-2313774302215552814styled-by-prettify">T</s=
pan><span style=3D"color:rgb(102,102,0)" class=3D"gmail-m_-2313774302215552=
814styled-by-prettify">>;</span><span style=3D"color:rgb(0,0,0)" class=
=3D"gmail-m_-2313774302215552814styled-by-prettify"><br></span></div></code=
></div></div></div></blockquote><div><br></div><div>I don't quite see w=
hat the former two lines are doing. You want things to be Relocatable iff t=
hey are TriviallyRelocatable? But what about things that are "relocata=
ble but non-trivially so"?=C2=A0 In P1144, that would be anything with=
a user-defined move-ctor and dtor; in your scheme, that would be anything =
with a user-defined `serialize` and `deserialize`.</div><div><br></div><div=
>I think pursuing this line might confuse both of us even more, so I'd =
be happy to drop it. :P</div><div><br></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px=
;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1e=
x"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style=
:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-=
left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">The rules fo=
r implicit serialize/deserialize generation could be:<br>If a type has (imp=
licitely or explicitly) defaulted move constructor and destructor (or move =
is not provided and copy is defaulted), serialize/deserialize are generated=
<br>In all other cases, serialize/deserialize will not be implicitly genera=
ted, but can still be explicitly defaulted.<br></div></blockquote><div><br>=
</div><div>If you follow down this path, you'll reach P1144's propo=
sed wording, except that where P1144 <a href=3D"https://quuxplusone.github.=
io/draft/d1144-object-relocation.html#wording-inheritance" rel=3D"nofollow"=
target=3D"_blank">says</a> "...or a class type declared with the [[tr=
ivially_relocatable]] attribute," you'll say "...or a class t=
ype with a trivial `operator serialize` <i>and</i> a trivial `operator dese=
rialize`."</div><div><br></div><div>Notice that I said "trivial&q=
uot;, not just "explicitly defaulted", because I guess that the d=
efault `operator {de,}serialize` should call the `operator {de,}serialize` =
of the base classes and members, perhaps? Or do you want `=3Ddefault` to <i=
>always</i> mean "no-op" even if some bases are non-trivially rel=
ocatable?</div></div></div></blockquote><div><br></div></span><div>I want d=
efault to call operator [de]serialize of subobjects. Otherwise, embedding a=
std::list would made the type trivially relocatable where it is not.</div>=
</div></blockquote><div><br></div><div>And later in your message, you write=
:</div><div><div dir=3D"ltr">> You missed a case: the type is relocatabl=
e because it "inherits" relocability from its subobject,</div><di=
v dir=3D"ltr">> and those can be relocatable without being trivially rel=
ocatable: std::list is an example.<br></div><div dir=3D"ltr"><br></div><div=
>Good point. Agreed.</div><div><br></div><span class=3D"gmail-"></span></di=
v><div>But does that conflict with your desire to have `operator serialize(=
) =3D default;` be the opt-in mechanism?</div><div>Two messages ago, I unde=
rstood you as wanting the following `One` to be trivially relocatable.</div=
><div><br></div><div><div><div>struct One {</div><div>=C2=A0 =C2=A0 std::ve=
ctor<int, offset_ptr_allocator<int>> vec; =C2=A0// nontrivially=
relocatable, or perhaps nonrelocatable</div><div>=C2=A0 =C2=A0 offset_ptr&=
lt;int> ptr_into_vec; =C2=A0// nontrivially relocatable, or perhaps nonr=
elocatable</div><div><br></div><div>=C2=A0 =C2=A0 // Warrant that "One=
" happens to be trivially relocatable for our purposes, even though it=
s individual members are not trivially relocatable</div><div>=C2=A0 =C2=A0 =
operator serialize() =3D default;</div><div>=C2=A0 =C2=A0 operator deserial=
ize() =3D default;</div><div>};</div></div></div><div><br></div><div><div>B=
ut now, as I understand your latest message, you want this `Two` to be=C2=
=A0<i>non</i>-trivially relocatable.</div><div><br></div></div><div>struct =
Two {</div><div>=C2=A0 =C2=A0 std::list<int> m; =C2=A0// nontrivially=
relocatable</div><div><br></div><div>=C2=A0 =C2=A0 // Ask the compiler to =
generate recursive definitions for these, i.e., they'll end up with non=
-trivial, non-noop definitions</div><div>=C2=A0 =C2=A0 operator serialize()=
=3D default;<br></div><div>=C2=A0 =C2=A0 operator deserialize() =3D defaul=
t;</div><div>};</div><div><br></div><div>How will the compiler tell the dif=
ference?</div><div>I suppose a valid answer would be that my `One` is not q=
uite right; that it should be</div><div><br></div><div><div><div>struct Thr=
ee {</div><div>=C2=A0 =C2=A0 std::vector<int, offset_ptr_allocator<in=
t>> vec; =C2=A0// nontrivially relocatable, or perhaps nonrelocatable=
</div><div>=C2=A0 =C2=A0 offset_ptr<int> ptr_into_vec; =C2=A0// nontr=
ivially relocatable, or perhaps nonrelocatable</div><div><br></div><div>=C2=
=A0 =C2=A0 // Warrant that "Three" happens to be trivially reloca=
table for our purposes, even though its individual members are not triviall=
y relocatable</div><div>=C2=A0 =C2=A0 operator serialize() {}</div><div>=C2=
=A0 =C2=A0 operator deserialize() {}</div><div>};</div></div></div><div><br=
></div><div>Here the core language cannot possibly tell that `operator seri=
alize` and `operator deserialize` are <i>trivial</i>, because they are user=
-provided; but we can throw ourselves on the mercy of a sufficiently smart =
inliner and expect that at least the compiler will generate efficient code =
for the (technically non-trivial) operation.</div><div><br></div><div>In ot=
her words, it sounds like your scheme is moving away from the idea of "=
;trivial"-anything-optimizing-into-memcpy at the library level, and to=
ward the idea that "serialize + memcpy + deserialize" should be t=
he <i>fundamental mechanism</i> used by the library to relocate anything (u=
nless it's not relocatable, in which case the library should fall back =
to move + destroy).</div><div><br></div><div><br></div><div>[...]</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"g=
mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-=
left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-styl=
e:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"lt=
r"><div>What do you gain from having all movable types relocatable? It is n=
ever said that swap only works for relocatable types.</div></div></blockquo=
te><div><br></div><div>What you gain is fewer branches in practice. Your `s=
wap` has to say</div><div>- if it's trivially relocatable, then memcpy =
+ memcpy + memcpy;</div><div>- else if it's nothrow relocatable, then s=
erialize + serialize + memcpy + memcpy + memcpy + deserialize + deserialize=
;</div><div>- (else if it's relocatable, can we figure out a way to do =
it exception-safely??)</div><div>- else move + move-assign + move-assign + =
destroy.</div><div>P1144's `swap` can just say</div><div><div>- if it&#=
39;s trivially relocatable, then memcpy + memcpy + memcpy;</div><div>- else=
move + move-assign + move-assign + destroy.<br></div></div></div></div></d=
iv></blockquote><div><br></div></span><div>First thing: why having more opt=
ional cases is bad? If there is too many cases to support, it is still fine=
to omit some of them.</div><div>Then, you wouldn't need to have a spec=
ial case for trivially relocatable as the loop of noop would be optimized a=
way: if it's trivial, the compiler knows for sure it's a noop.</div=
></div></blockquote><div><br></div><div>If you omit some of the cases, then=
your library has poor Quality of Implementation and your competitors make =
fun of you.</div><div>If you don't omit any of the cases, then your lib=
rary takes longer to implement and test and debug.</div><div>One way out of=
this dilemma is to make the optimal specification have <i>fewer cases to b=
egin with</i>.</div><div><br></div><div><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bord=
er-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div clas=
s=3D"gmail_quote">[...]<br></div></div></blockquote></span><span class=3D"g=
mail-"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204=
,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi=
dth:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-=
left:1ex"><div dir=3D"ltr"><div>Your swap is basically the same as mine. Ex=
cept I can handle user-defined relocation.<br></div></div></blockquote><div=
><br></div><div>Agreed. And I can handle user-defined move and destroy (as =
can you).=C2=A0 So my question for you now is, what's a situation where=
a type might have user-defined "serialize/deserialize" operation=
s, <i>and</i> some kind of "move/destroy" operations (so that it =
remains swappable by the C++17 definition), but where "serialize/deser=
ialize" is <i>faster</i> than "move/destroy"?</div><div><br>=
</div><div>That is, in the current iteration of your idea, both of us can e=
fficiently swap</div><div>=C2=A0 =C2=A0 struct One {</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 std::unique_ptr<int> p;</div><div>=C2=A0 =C2=A0 };<=
/div><div>and both of us can inefficiently swap</div><div>=C2=A0 =C2=A0 str=
uct Two {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 hypothetically_relocatable:=
:of<wbr>fset_ptr<int> q;</div><div>=C2=A0 =C2=A0 };</div><div>=E2=80=
=94 you would do `Two` via serialize/serialize/memcpy/mem<wbr>cpy/memcpy/de=
serialize/deseria<wbr>lize, whereas I would immediately fall all the way ba=
ck to moveconstruct/moveassign/movea<wbr>ssign/(trivial-destroy).</div></di=
v></div></blockquote><div><br></div></span><div>I've just made a quick =
exmaple in godbolt of what you can gain from relocatable type that are not =
trivially relocatable: <a href=3D"https://godbolt.org/g/wNDeGp" target=3D"_=
blank">https://godbolt.org/g/wNDeGp</a><br></div><div>=C2=A0</div><div>You =
can see how cleaner the relocatable is compared to the non-relocatable.</di=
v></div></blockquote><div><br></div><div><a href=3D"https://godbolt.org/g/F=
Mo62c">Here's a reduced Godbolt</a>=C2=A0with the two swap functions si=
de-by-side.=C2=A0 Indeed, that is very cool!</div><div>I admit that, as far=
as I know, P1144 cannot do that for std::list.</div><div><br></div><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,20=
4,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width=
:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-lef=
t:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><div>Basically, when you say "relocatable", you =
just say "movable", and only trivially relocatable has a special =
meaning. That's not something I find useful.</div></div></blockquote><d=
iv><br></div><div>But I find it useful, mainly for vector::resize (which is=
really just standardizing existing practice as seen in <a href=3D"https://=
github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocat=
ion" rel=3D"nofollow" target=3D"_blank">Folly's FBVector</a> and <a hre=
f=3D"https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911=
d05c85e7ba75120/include/EASTL/deque.h#L1791" rel=3D"nofollow" target=3D"_bl=
ank">EASTL's deque</a>).</div></div></div></div></blockquote><div><br><=
/div></span><div>That's exactly where I think it is not useful: vector:=
:resize could be implemented with std::realloc for relocatable types, even =
if relocation is not trivial (see my godbolt implementation above).</div><d=
iv>But std::realloc cannot work with move+destroy.<br></div><span class=3D"=
gmail-"><div></div></span></div></blockquote><div><br></div><div>Right. If =
our goal is to reallocate an array of `std::list` objects, then=C2=A0your s=
cheme can use "serialize in a loop + realloc + deserialize in a loop.&=
quot;</div><div>P1144 cannot possibly use realloc in that scenario, and mus=
t fall back to "malloc + (move+destroy) in a loop + free."</div><=
div><br></div><div>This applies to `std::list` because it is non-trivially =
relocatable. To reallocate an array of `std::deque` objects, your scheme wo=
uld use "serialize in a loop + realloc + deserialize in a loop" a=
nd mine would use "(unbless?) + realloc + (bless?)," i.e., we'=
;d be equivalent.</div><div><br></div><div>(Pedantic note that in practice,=
`<b>std</b>::vector` cannot possibly use `realloc` because it must behave =
as-if it were using `allocator_traits::allocate` and `allocator_traits::dea=
llocate`. To actually make it use `realloc` you'd first have to make an=
allocator type that used `malloc` and `free` instead of `operator new` and=
`operator delete`, and then you'd have to teach `std::vector` about th=
at allocator type as a special case. But I can certainly imagine a nonstd::=
vector =E2=80=94 either non-allocator-aware, or allocator-aware using a ric=
her allocator model than the standard C++17 allocator model =E2=80=94 that =
would want the ability to do this optimization. Also, even if we don't =
permit `realloc`, your scheme still does</div><div>=C2=A0 =C2=A0 allocate +=
serialize in a loop + memcpy + deserialize in a loop + deallocate</div><di=
v>whereas P1144 does</div><div>=C2=A0 =C2=A0 allocate + (move+destroy) in a=
loop + deallocate<br></div><div>.)</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:so=
lid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote"><div>I would also find this serialize/deseri=
alize mechanism useful, <i><b>if</b></i> it could be used in the way you ap=
parently envision for it to be used, to "wormhole" position-indep=
endent object representations across process boundaries or from page to pag=
e without a physical memcpy operation.=C2=A0 Unfortunately, as I said, posi=
tion-independence is a property of a whole region of memory; it's not a=
property of an individual typed object.</div></div></div></div></blockquot=
e><div><br></div></span><div>I agree for interprocess communication. But I&=
#39;m not convinced if we stay within the bounds of our program. std:reallo=
c is this kind of wormhole.</div></div></blockquote><div><br></div><div>Agr=
eed. So "reallocate an array of `std::list` objects" becomes the =
killer app for the serialize+deserialize approach?=C2=A0 And we haven't=
made any particular progress on the interprocess case?</div><div><br></div=
><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0Kfb8c6VafR7xCXQc3Mvi_HmCJJwvHB=
diRRjJcomokp%3Dg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0Kfb8c6Va=
fR7xCXQc3Mvi_HmCJJwvHBdiRRjJcomokp%3Dg%40mail.gmail.com</a>.<br />
--000000000000db01e20573599222--
.
Author: florian.csdt@gmail.com
Date: Tue, 14 Aug 2018 01:11:23 -0700 (PDT)
Raw View
------=_Part_1901_1190175759.1534234284056
Content-Type: multipart/alternative;
boundary="----=_Part_1902_1825704649.1534234284058"
------=_Part_1902_1825704649.1534234284058
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 14 ao=C3=BBt 2018 01:37:19 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Mon, Aug 13, 2018 at 3:11 PM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>> Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>>
>>> On Mon, Aug 13, 2018 at 2:52 AM, <floria...@gmail.com> wrote:
>>>
>>>>
>>>> You seem to want all movable types to also be relocatable by saying: i=
f=20
>>>> a type is not trivially relocatable, then relocate =3D memcpy + destro=
y.
>>>> What I propose is that some types will not be relocatable at all (more=
=20
>>>> on this later). And the fallback is written by the user because it hig=
hly=20
>>>> depends on where relocation is used.
>>>> For instance, there is no way to emulate serialize+realloc+deserialize=
=20
>>>> with your form of fallback.
>>>> As I don't provide any automatic fallback at the language level, the=
=20
>>>> user (might be a library writer) will need to write the fallback code=
=20
>>>> themselves (here: allocate+move+destroy+deallocate).
>>>>
>>>> So when you say "in my design, T is relocatable", I will now=20
>>>> understand: "T is movable and non relocatable; serialize+memcpy+deseri=
alize=20
>>>> could be emulated by move+destroy".
>>>> But I fail to see what you gain from this.
>>>>
>>>
>>> Our definitions are converging! This is good news. :)
>>>
>>> I am not too worried that you fail to see what we gain from P1144's=20
>>> definition of relocation (over yours), because vice versa I fail to see=
=20
>>> what we gain from your definition of relocation (over P1144's). I thin=
k=20
>>> that as we plug the holes in your definition, it is quickly converging =
to=20
>>> *almost* the same thing as P1144; therefore both definitions have just=
=20
>>> about the same advantages and disadvantages. The only thing I would tou=
t as=20
>>> a remaining major advantage of P1144 is that it has a proposal with wor=
ding=20
>>> and a complete implementation on Godbolt =E2=80=94 and I will happily a=
dmit that=20
>>> this is purely circumstantial and does not necessarily indicate that yo=
urs=20
>>> *couldn't* have such an implementation (now that most of the holes are=
=20
>>> plugged).
>>>
>>
>> As I said quite a while ago, our two proposals are not mutually=20
>> exclusive. It is possible to modify slightly yours to let the possibilit=
y=20
>> to standardize mine.
>> The only modification really necessary would be:
>> template <class T> concept Relocatable =3D NothrowRelocatable<T>;
>> template <class T> concept NothrowRelocatable =3D TriviallyRelocatable<T=
>;
>> instead of:
>> template <class T> concept Relocatable =3D MoveConstructible<T> &&=20
>> Destructible<T>;
>> template <class T> concept NothrowRelocatable =3D NothrowMoveConstructib=
le<
>> T> && NothrowDestructible<T>;
>>
>
> I don't quite see what the former two lines are doing. You want things to=
=20
> be Relocatable iff they are TriviallyRelocatable? But what about things=
=20
> that are "relocatable but non-trivially so"? In P1144, that would be=20
> anything with a user-defined move-ctor and dtor; in your scheme, that wou=
ld=20
> be anything with a user-defined `serialize` and `deserialize`.
>
> I think pursuing this line might confuse both of us even more, so I'd be=
=20
> happy to drop it. :P
>
Basically, the latter is what you have in your proposal currently.
And the former is what I propose for your proposal to be completely forward=
=20
compatible with mine.
Because widening a contract is easy, but narrowing is almost impossible.
=20
>
> =20
>
>> The rules for implicit serialize/deserialize generation could be:
>>>> If a type has (implicitely or explicitly) defaulted move constructor=
=20
>>>> and destructor (or move is not provided and copy is defaulted),=20
>>>> serialize/deserialize are generated
>>>> In all other cases, serialize/deserialize will not be implicitly=20
>>>> generated, but can still be explicitly defaulted.
>>>>
>>>
>>> If you follow down this path, you'll reach P1144's proposed wording,=20
>>> except that where P1144 says=20
>>> <https://quuxplusone.github.io/draft/d1144-object-relocation.html#wordi=
ng-inheritance>=20
>>> "...or a class type declared with the [[trivially_relocatable]] attribu=
te,"=20
>>> you'll say "...or a class type with a trivial `operator serialize` *and=
*=20
>>> a trivial `operator deserialize`."
>>>
>>> Notice that I said "trivial", not just "explicitly defaulted", because =
I=20
>>> guess that the default `operator {de,}serialize` should call the `opera=
tor=20
>>> {de,}serialize` of the base classes and members, perhaps? Or do you wan=
t=20
>>> `=3Ddefault` to *always* mean "no-op" even if some bases are=20
>>> non-trivially relocatable?
>>>
>>
>> I want default to call operator [de]serialize of subobjects. Otherwise,=
=20
>> embedding a std::list would made the type trivially relocatable where it=
is=20
>> not.
>>
>
> And later in your message, you write:
> > You missed a case: the type is relocatable because it "inherits"=20
> relocability from its subobject,
> > and those can be relocatable without being trivially relocatable:=20
> std::list is an example.
>
> Good point. Agreed.
>
> But does that conflict with your desire to have `operator serialize() =3D=
=20
> default;` be the opt-in mechanism?
>
No, because if a user follows the rule of 0 (or the rule of 5 defaults),=20
they would have operator [de]serialize implicitly defaulted.
But as soon as you write a custom move constructor, you don't have any=20
implicit generation at all.
=20
> Two messages ago, I understood you as wanting the following `One` to be=
=20
> trivially relocatable.
>
> struct One {
> std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially=20
> relocatable, or perhaps nonrelocatable
> offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or perhap=
s=20
> nonrelocatable
>
> // Warrant that "One" happens to be trivially relocatable for our=20
> purposes, even though its individual members are not trivially relocatabl=
e
> operator serialize() =3D default;
> operator deserialize() =3D default;
> };
>
You convinced me that an offset_ptr shouldn't be relocatable, so let be it=
=20
(which is the default anyway as offset_ptr move constructor is not trivial)=
..
One will then "inherits" the non-relocalibility from offset_ptr.
=20
>
> But now, as I understand your latest message, you want this `Two` to be=
=20
> *non*-trivially relocatable.
>
> struct Two {
> std::list<int> m; // nontrivially relocatable
>
> // Ask the compiler to generate recursive definitions for these, i.e.=
,=20
> they'll end up with non-trivial, non-noop definitions
> operator serialize() =3D default;
> operator deserialize() =3D default;
> };
>
> How will the compiler tell the difference?
>
Here, std::list is relocatable, the Two will also be.
It is the same mechanism in the 2 examples, your object "inherits" the=20
[non-]relocalibility from its subobjects.
=20
> I suppose a valid answer would be that my `One` is not quite right; that=
=20
> it should be
>
> struct Three {
> std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially=20
> relocatable, or perhaps nonrelocatable
> offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or perhap=
s=20
> nonrelocatable
>
> // Warrant that "Three" happens to be trivially relocatable for our=
=20
> purposes, even though its individual members are not trivially relocatabl=
e
> operator serialize() {}
> operator deserialize() {}
> };
>
> Here the core language cannot possibly tell that `operator serialize` and=
=20
> `operator deserialize` are *trivial*, because they are user-provided; but=
=20
> we can throw ourselves on the mercy of a sufficiently smart inliner and=
=20
> expect that at least the compiler will generate efficient code for the=20
> (technically non-trivial) operation.
>
That's the idea. Here, to solve this minor issue, your attribute might come=
=20
handy.
=20
>
> In other words, it sounds like your scheme is moving away from the idea o=
f=20
> "trivial"-anything-optimizing-into-memcpy at the library level, and towar=
d=20
> the idea that "serialize + memcpy + deserialize" should be the *fundament=
al=20
> mechanism* used by the library to relocate anything (unless it's not=20
> relocatable, in which case the library should fall back to move + destroy=
).
>
>
This is exactly what I have in mind from the very start.
Also, the "memcpy" part is not bound to memcpy, but can be std::realloc for=
=20
instance (it is moving bytes around).
=20
>
> [...]
>
>> What do you gain from having all movable types relocatable? It is never=
=20
>>>> said that swap only works for relocatable types.
>>>>
>>>
>>> What you gain is fewer branches in practice. Your `swap` has to say
>>> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
>>> - else if it's nothrow relocatable, then serialize + serialize + memcpy=
=20
>>> + memcpy + memcpy + deserialize + deserialize;
>>> - (else if it's relocatable, can we figure out a way to do it=20
>>> exception-safely??)
>>> - else move + move-assign + move-assign + destroy.
>>> P1144's `swap` can just say
>>> - if it's trivially relocatable, then memcpy + memcpy + memcpy;
>>> - else move + move-assign + move-assign + destroy.
>>>
>>
>> First thing: why having more optional cases is bad? If there is too many=
=20
>> cases to support, it is still fine to omit some of them.
>> Then, you wouldn't need to have a special case for trivially relocatable=
=20
>> as the loop of noop would be optimized away: if it's trivial, the compil=
er=20
>> knows for sure it's a noop.
>>
>
> If you omit some of the cases, then your library has poor Quality of=20
> Implementation and your competitors make fun of you.
> If you don't omit any of the cases, then your library takes longer to=20
> implement and test and debug.
> One way out of this dilemma is to make the optimal specification have *fe=
wer=20
> cases to begin with*.
>
>
In that case anyway, the number of different cases is 2: the same as with=
=20
your proposal.
Also, if cases are optional, the implementation can be done in an=20
incremental way.
=20
>
> [...]
>>>
>> Your swap is basically the same as mine. Except I can handle user-define=
d=20
>>>> relocation.
>>>>
>>>
>>> Agreed. And I can handle user-defined move and destroy (as can you). S=
o=20
>>> my question for you now is, what's a situation where a type might have=
=20
>>> user-defined "serialize/deserialize" operations, *and* some kind of=20
>>> "move/destroy" operations (so that it remains swappable by the C++17=20
>>> definition), but where "serialize/deserialize" is *faster* than=20
>>> "move/destroy"?
>>>
>>> That is, in the current iteration of your idea, both of us can=20
>>> efficiently swap
>>> struct One {
>>> std::unique_ptr<int> p;
>>> };
>>> and both of us can inefficiently swap
>>> struct Two {
>>> hypothetically_relocatable::offset_ptr<int> q;
>>> };
>>> =E2=80=94 you would do `Two` via=20
>>> serialize/serialize/memcpy/memcpy/memcpy/deserialize/deserialize, where=
as I=20
>>> would immediately fall all the way back to=20
>>> moveconstruct/moveassign/moveassign/(trivial-destroy).
>>>
>>
>> I've just made a quick exmaple in godbolt of what you can gain from=20
>> relocatable type that are not trivially relocatable:=20
>> https://godbolt.org/g/wNDeGp
>> =20
>> You can see how cleaner the relocatable is compared to the=20
>> non-relocatable.
>>
>
> Here's a reduced Godbolt <https://godbolt.org/g/FMo62c> with the two swap=
=20
> functions side-by-side. Indeed, that is very cool!
> I admit that, as far as I know, P1144 cannot do that for std::list.
>
>
Thank you for this size-by-size view. I should really learn how to use all=
=20
those feature from compiler explorer.
=20
>
> Basically, when you say "relocatable", you just say "movable", and only=
=20
>>>> trivially relocatable has a special meaning. That's not something I fi=
nd=20
>>>> useful.
>>>>
>>>
>>> But I find it useful, mainly for vector::resize (which is really just=
=20
>>> standardizing existing practice as seen in Folly's FBVector=20
>>> <https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#o=
bject-relocation>=20
>>> and EASTL's deque=20
>>> <https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40ea7911=
d05c85e7ba75120/include/EASTL/deque.h#L1791>
>>> ).
>>>
>>
>> That's exactly where I think it is not useful: vector::resize could be=
=20
>> implemented with std::realloc for relocatable types, even if relocation =
is=20
>> not trivial (see my godbolt implementation above).
>> But std::realloc cannot work with move+destroy.
>>
>
> Right. If our goal is to reallocate an array of `std::list` objects,=20
> then your scheme can use "serialize in a loop + realloc + deserialize in =
a=20
> loop."
> P1144 cannot possibly use realloc in that scenario, and must fall back to=
=20
> "malloc + (move+destroy) in a loop + free."
>
> This applies to `std::list` because it is non-trivially relocatable. To=
=20
> reallocate an array of `std::deque` objects, your scheme would use=20
> "serialize in a loop + realloc + deserialize in a loop" and mine would us=
e=20
> "(unbless?) + realloc + (bless?)," i.e., we'd be equivalent.
>
Yes. Basically, the two are equivalent for all trivially relocatable types=
=20
(for which, we have compatible definitions).
=20
>
> (Pedantic note that in practice, `*std*::vector` cannot possibly use=20
> `realloc` because it must behave as-if it were using=20
> `allocator_traits::allocate` and `allocator_traits::deallocate`. To=20
> actually make it use `realloc` you'd first have to make an allocator type=
=20
> that used `malloc` and `free` instead of `operator new` and `operator=20
> delete`, and then you'd have to teach `std::vector` about that allocator=
=20
> type as a special case. But I can certainly imagine a nonstd::vector =E2=
=80=94=20
> either non-allocator-aware, or allocator-aware using a richer allocator=
=20
> model than the standard C++17 allocator model =E2=80=94 that would want t=
he ability=20
> to do this optimization. Also, even if we don't permit `realloc`, your=20
> scheme still does
> allocate + serialize in a loop + memcpy + deserialize in a loop +=20
> deallocate
> whereas P1144 does
> allocate + (move+destroy) in a loop + deallocate
> .)
>
I know all of that. Actually, that's where I started to think about=20
relocation in the first place.
I might write some stuff about memory allocations in the futur.
=20
>
> I would also find this serialize/deserialize mechanism useful, *if* it=20
>>> could be used in the way you apparently envision for it to be used, to=
=20
>>> "wormhole" position-independent object representations across process=
=20
>>> boundaries or from page to page without a physical memcpy operation. =
=20
>>> Unfortunately, as I said, position-independence is a property of a whol=
e=20
>>> region of memory; it's not a property of an individual typed object.
>>>
>>
>> I agree for interprocess communication. But I'm not convinced if we stay=
=20
>> within the bounds of our program. std:realloc is this kind of wormhole.
>>
>
> Agreed. So "reallocate an array of `std::list` objects" becomes the kille=
r=20
> app for the serialize+deserialize approach? And we haven't made any=20
> particular progress on the interprocess case?
>
> =E2=80=93Arthur
>
Yes, that would be it. To be fair, I think that's already quite good.
Also, I have the impression that my proposal is a step forward to=20
standardize interprocess communication despite saying nothing about it.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/5c5b1132-fd6a-46cb-939c-8eb8d7e26a47%40isocpp.or=
g.
------=_Part_1902_1825704649.1534234284058
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 14 ao=C3=BBt 2018 01:37:19 UTC+2, Arthur =
O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr">On Mon, Aug 13, 2018 at 3:11 PM, <span dir=3D"ltr"><<=
a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"lsSEZQ5ND=
gAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';retu=
rn true;" onclick=3D"this.href=3D'javascript:';return true;">floria=
....@gmail.com</a>></span> wrote:<div><div class=3D"gmail_quote"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-l=
eft:1ex"><div dir=3D"ltr">Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur=
O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:soli=
d;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">On =
Mon, Aug 13, 2018 at 2:52 AM, <span dir=3D"ltr"><<a rel=3D"nofollow">fl=
oria...@gmail.com</a>></span> wrote:<br><div><div class=3D"gmail_quote">=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);p=
adding-left:1ex"><div dir=3D"ltr"><br>You seem to want all movable types to=
also be relocatable by saying: if a type is not trivially relocatable, the=
n relocate =3D memcpy + destroy.<br>What I propose is that some types will =
not be relocatable at all (more on this later). And the fallback is written=
by the user because it highly depends on where relocation is used.<br>For =
instance, there is no way to emulate serialize+realloc+deserialize with you=
r form of fallback.<br>As I don't provide any automatic fallback at the=
language level, the user (might be a library writer) will need to write th=
e fallback code themselves (here: allocate+move+destroy+<wbr>deallocate).<b=
r><br>So when you say "in my design, T is relocatable", I will no=
w understand: "T is movable and non relocatable; serialize+memcpy+dese=
rialize could be emulated by move+destroy".<br>But I fail to see what =
you gain from this.<br></div></blockquote><div><br></div><div>Our definitio=
ns are converging!=C2=A0 This is good news. :)</div><div><br></div><div>I a=
m not too worried that you fail to see what we gain from P1144's defini=
tion of relocation (over yours), because vice versa I fail to see what we g=
ain from your definition of relocation (over P1144's).=C2=A0 I think th=
at as we plug the holes in your definition, it is quickly converging to <i>=
almost</i> the same thing as P1144; therefore both definitions have just ab=
out the same advantages and disadvantages. The only thing I would tout as a=
remaining major advantage of P1144 is that it has a proposal with wording =
and a complete implementation on Godbolt =E2=80=94 and I will happily admit=
that this is purely circumstantial and does not necessarily indicate that =
yours <i>couldn't</i> have such an implementation (now that most of the=
holes are plugged).</div></div></div></div></blockquote><div><br></div></s=
pan><div>As I said quite a while ago, our two proposals are not mutually ex=
clusive. It is possible to modify slightly yours to let the possibility to =
standardize mine.</div><div>The only modification really necessary would be=
:</div><div><div style=3D"background-color:rgb(250,250,250);border:1px soli=
d rgb(187,187,187)"><code><div><span style=3D"color:rgb(0,0,136)">template<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102=
,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span><span st=
yle=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb(102,102,0)">>=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,=
0,136)">concept</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,0,102)">Relocatable</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">NothrowRelocata=
ble</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"co=
lor:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">>;</span><s=
pan style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)=
">template</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</sp=
an><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb(102,1=
02,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,0,102)">NothrowRelocatable</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)=
">TriviallyRelocatable</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102=
,0)">>;</span><span style=3D"color:rgb(0,0,0)"><br></span></div></code><=
/div>instead of:</div><div><div style=3D"background-color:rgb(250,250,250);=
border:1px solid rgb(187,187,187)"><code><div><span style=3D"color:rgb(0,0,=
136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">cla=
ss</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb=
(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span styl=
e=3D"color:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">Relocatable</span><span style=3D"=
color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)"=
>MoveConstructible</span><span style=3D"color:rgb(102,102,0)"><</span><s=
pan style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)"=
>></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:r=
gb(102,102,0)">&&</span><span style=3D"color:rgb(0,0,0)"> </span><s=
pan style=3D"color:rgb(102,0,102)">Destructible</span><span style=3D"color:=
rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span s=
tyle=3D"color:rgb(102,102,0)">>;</span><span style=3D"color:rgb(0,0,0)">=
<br></span><span style=3D"color:rgb(0,0,136)">template</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</span>=
<span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0=
,0)"> T</span><span style=3D"color:rgb(102,102,0)">></span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">concept</s=
pan><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0=
,102)">NothrowRelocatable</span><span style=3D"color:rgb(0,0,0)"> </span><s=
pan style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0=
)"> </span><span style=3D"color:rgb(102,0,102)">NothrowMoveConstructible</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rg=
b(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">></span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">&&=
amp;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,0,102)">NothrowDestructible</span><span style=3D"color:rgb(102,102,0)=
"><</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:=
rgb(102,102,0)">>;</span><span style=3D"color:rgb(0,0,0)"><br></span></d=
iv></code></div></div></div></blockquote><div><br></div><div>I don't qu=
ite see what the former two lines are doing. You want things to be Relocata=
ble iff they are TriviallyRelocatable? But what about things that are "=
;relocatable but non-trivially so"?=C2=A0 In P1144, that would be anyt=
hing with a user-defined move-ctor and dtor; in your scheme, that would be =
anything with a user-defined `serialize` and `deserialize`.</div><div><br><=
/div><div>I think pursuing this line might confuse both of us even more, so=
I'd be happy to drop it. :P</div></div></div></div></blockquote><div><=
br></div><div>Basically, the latter is what you have in your proposal curre=
ntly.</div><div>And the former is what I propose for your proposal to be co=
mpletely forward compatible with mine.</div><div><br></div><div>Because wid=
ening a contract is easy, but narrowing is almost impossible.<br></div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div><br></div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-=
left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr">The rules for implicit s=
erialize/deserialize generation could be:<br>If a type has (implicitely or =
explicitly) defaulted move constructor and destructor (or move is not provi=
ded and copy is defaulted), serialize/deserialize are generated<br>In all o=
ther cases, serialize/deserialize will not be implicitly generated, but can=
still be explicitly defaulted.<br></div></blockquote><div><br></div><div>I=
f you follow down this path, you'll reach P1144's proposed wording,=
except that where P1144 <a href=3D"https://quuxplusone.github.io/draft/d11=
44-object-relocation.html#wording-inheritance" rel=3D"nofollow" target=3D"_=
blank" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttp=
s%3A%2F%2Fquuxplusone.github.io%2Fdraft%2Fd1144-object-relocation.html%23wo=
rding-inheritance\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEic9fQlJSQs-EmoSq=
aDjDCwLI3rQ';return true;" onclick=3D"this.href=3D'https://www.goog=
le.com/url?q\x3dhttps%3A%2F%2Fquuxplusone.github.io%2Fdraft%2Fd1144-object-=
relocation.html%23wording-inheritance\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQ=
jCNEic9fQlJSQs-EmoSqaDjDCwLI3rQ';return true;">says</a> "...or a c=
lass type declared with the [[trivially_relocatable]] attribute," you&=
#39;ll say "...or a class type with a trivial `operator serialize` <i>=
and</i> a trivial `operator deserialize`."</div><div><br></div><div>No=
tice that I said "trivial", not just "explicitly defaulted&q=
uot;, because I guess that the default `operator {de,}serialize` should cal=
l the `operator {de,}serialize` of the base classes and members, perhaps? O=
r do you want `=3Ddefault` to <i>always</i> mean "no-op" even if =
some bases are non-trivially relocatable?</div></div></div></blockquote><di=
v><br></div></span><div>I want default to call operator [de]serialize of su=
bobjects. Otherwise, embedding a std::list would made the type trivially re=
locatable where it is not.</div></div></blockquote><div><br></div><div>And =
later in your message, you write:</div><div><div dir=3D"ltr">> You misse=
d a case: the type is relocatable because it "inherits" relocabil=
ity from its subobject,</div><div dir=3D"ltr">> and those can be relocat=
able without being trivially relocatable: std::list is an example.<br></div=
><div dir=3D"ltr"><br></div><div>Good point. Agreed.</div><div><br></div><s=
pan></span></div><div>But does that conflict with your desire to have `oper=
ator serialize() =3D default;` be the opt-in mechanism?</div></div></div></=
div></blockquote><div><br></div><div>No, because if a user follows the rule=
of 0 (or the rule of 5 defaults), they would have operator [de]serialize i=
mplicitly defaulted.</div><div>But as soon as you write a custom move const=
ructor, you don't have any implicit generation at all.<br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote"><div>Two messages ago, I understood you as w=
anting the following `One` to be trivially relocatable.</div><div><br></div=
><div><div><div>struct One {</div><div>=C2=A0 =C2=A0 std::vector<int, of=
fset_ptr_allocator<int>> vec; =C2=A0// nontrivially relocatable, o=
r perhaps nonrelocatable</div><div>=C2=A0 =C2=A0 offset_ptr<int> ptr_=
into_vec; =C2=A0// nontrivially relocatable, or perhaps nonrelocatable</div=
><div><br></div><div>=C2=A0 =C2=A0 // Warrant that "One" happens =
to be trivially relocatable for our purposes, even though its individual me=
mbers are not trivially relocatable</div><div>=C2=A0 =C2=A0 operator serial=
ize() =3D default;</div><div>=C2=A0 =C2=A0 operator deserialize() =3D defau=
lt;</div><div>};</div></div></div></div></div></div></blockquote><div><br><=
/div><div>You convinced me that an offset_ptr shouldn't be relocatable,=
so let be it (which is the default anyway as offset_ptr move constructor i=
s not trivial).</div><div>One will then "inherits" the non-reloca=
libility from offset_ptr.<br></div><div>=C2=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div=
><br></div><div><div>But now, as I understand your latest message, you want=
this `Two` to be=C2=A0<i>non</i>-trivially relocatable.</div><div><br></di=
v></div><div>struct Two {</div><div>=C2=A0 =C2=A0 std::list<int> m; =
=C2=A0// nontrivially relocatable</div><div><br></div><div>=C2=A0 =C2=A0 //=
Ask the compiler to generate recursive definitions for these, i.e., they&#=
39;ll end up with non-trivial, non-noop definitions</div><div>=C2=A0 =C2=A0=
operator serialize() =3D default;<br></div><div>=C2=A0 =C2=A0 operator des=
erialize() =3D default;</div><div>};</div><div><br></div><div>How will the =
compiler tell the difference?</div></div></div></div></blockquote><div><br>=
</div><div>Here, std::list is relocatable, the Two will also be.</div><div>=
It is the same mechanism in the 2 examples, your object "inherits"=
; the [non-]relocalibility from its subobjects.<br></div><div>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><div>I suppose a valid answer would be that my `One` is n=
ot quite right; that it should be</div><div><br></div><div><div><div>struct=
Three {</div><div>=C2=A0 =C2=A0 std::vector<int, offset_ptr_allocator&l=
t;int>> vec; =C2=A0// nontrivially relocatable, or perhaps nonrelocat=
able</div><div>=C2=A0 =C2=A0 offset_ptr<int> ptr_into_vec; =C2=A0// n=
ontrivially relocatable, or perhaps nonrelocatable</div><div><br></div><div=
>=C2=A0 =C2=A0 // Warrant that "Three" happens to be trivially re=
locatable for our purposes, even though its individual members are not triv=
ially relocatable</div><div>=C2=A0 =C2=A0 operator serialize() {}</div><div=
>=C2=A0 =C2=A0 operator deserialize() {}</div><div>};</div></div></div><div=
><br></div><div>Here the core language cannot possibly tell that `operator =
serialize` and `operator deserialize` are <i>trivial</i>, because they are =
user-provided; but we can throw ourselves on the mercy of a sufficiently sm=
art inliner and expect that at least the compiler will generate efficient c=
ode for the (technically non-trivial) operation.</div></div></div></div></b=
lockquote><div><br></div><div>That's the idea. Here, to solve this mino=
r issue, your attribute might come handy.<br></div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote"><div><br></div><div>In other words, it sounds like your scheme =
is moving away from the idea of "trivial"-anything-optimizing-<wb=
r>into-memcpy at the library level, and toward the idea that "serializ=
e + memcpy + deserialize" should be the <i>fundamental mechanism</i> u=
sed by the library to relocate anything (unless it's not relocatable, i=
n which case the library should fall back to move + destroy).</div><div><br=
></div></div></div></div></blockquote><div><br></div><div>This is exactly w=
hat I have in mind from the very start.</div><div>Also, the "memcpy&qu=
ot; part is not bound to memcpy, but can be std::realloc for instance (it i=
s moving bytes around).<br></div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><=
/div><div><br></div><div>[...]</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);=
padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-l=
eft:1ex"><div dir=3D"ltr"><div>What do you gain from having all movable typ=
es relocatable? It is never said that swap only works for relocatable types=
..</div></div></blockquote><div><br></div><div>What you gain is fewer branch=
es in practice. Your `swap` has to say</div><div>- if it's trivially re=
locatable, then memcpy + memcpy + memcpy;</div><div>- else if it's noth=
row relocatable, then serialize + serialize + memcpy + memcpy + memcpy + de=
serialize + deserialize;</div><div>- (else if it's relocatable, can we =
figure out a way to do it exception-safely??)</div><div>- else move + move-=
assign + move-assign + destroy.</div><div>P1144's `swap` can just say</=
div><div><div>- if it's trivially relocatable, then memcpy + memcpy + m=
emcpy;</div><div>- else move + move-assign + move-assign + destroy.<br></di=
v></div></div></div></div></blockquote><div><br></div></span><div>First thi=
ng: why having more optional cases is bad? If there is too many cases to su=
pport, it is still fine to omit some of them.</div><div>Then, you wouldn=
9;t need to have a special case for trivially relocatable as the loop of no=
op would be optimized away: if it's trivial, the compiler knows for sur=
e it's a noop.</div></div></blockquote><div><br></div><div>If you omit =
some of the cases, then your library has poor Quality of Implementation and=
your competitors make fun of you.</div><div>If you don't omit any of t=
he cases, then your library takes longer to implement and test and debug.</=
div><div>One way out of this dilemma is to make the optimal specification h=
ave <i>fewer cases to begin with</i>.</div><div><br></div></div></div></div=
></blockquote><div><br></div><div>In that case anyway, the number of differ=
ent cases is 2: the same as with your proposal.</div><div>Also, if cases ar=
e optional, the implementation can be done in an incremental way.<br></div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div></div><div><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1=
ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-le=
ft-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"=
gmail_quote">[...]<br></div></div></blockquote></span><span><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex=
"><div dir=3D"ltr"><div class=3D"gmail_quote"><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-st=
yle:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"=
ltr"><div>Your swap is basically the same as mine. Except I can handle user=
-defined relocation.<br></div></div></blockquote><div><br></div><div>Agreed=
.. And I can handle user-defined move and destroy (as can you).=C2=A0 So my =
question for you now is, what's a situation where a type might have use=
r-defined "serialize/deserialize" operations, <i>and</i> some kin=
d of "move/destroy" operations (so that it remains swappable by t=
he C++17 definition), but where "serialize/deserialize" is <i>fas=
ter</i> than "move/destroy"?</div><div><br></div><div>That is, in=
the current iteration of your idea, both of us can efficiently swap</div><=
div>=C2=A0 =C2=A0 struct One {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 std::u=
nique_ptr<int> p;</div><div>=C2=A0 =C2=A0 };</div><div>and both of us=
can inefficiently swap</div><div>=C2=A0 =C2=A0 struct Two {</div><div>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 hypothetically_relocatable::<wbr>offset_ptr<int=
> q;</div><div>=C2=A0 =C2=A0 };</div><div>=E2=80=94 you would do `Two` v=
ia serialize/serialize/memcpy/<wbr>memcpy/memcpy/deserialize/<wbr>deseriali=
ze, whereas I would immediately fall all the way back to moveconstruct/move=
assign/<wbr>moveassign/(trivial-destroy).</div></div></div></blockquote><di=
v><br></div></span><div>I've just made a quick exmaple in godbolt of wh=
at you can gain from relocatable type that are not trivially relocatable: <=
a href=3D"https://godbolt.org/g/wNDeGp" target=3D"_blank" rel=3D"nofollow" =
onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F=
%2Fgodbolt.org%2Fg%2FwNDeGp\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFEQjc4U=
4MmNXDuLgD2i73QdhmCQA';return true;" onclick=3D"this.href=3D'https:=
//www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FwNDeGp\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNFEQjc4U4MmNXDuLgD2i73QdhmCQA';return true=
;">https://godbolt.org/g/wNDeGp</a><br></div><div>=C2=A0</div><div>You can =
see how cleaner the relocatable is compared to the non-relocatable.</div></=
div></blockquote><div><br></div><div><a href=3D"https://godbolt.org/g/FMo62=
c" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https=
://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FFMo62c\x26sa\x3d=
D\x26sntz\x3d1\x26usg\x3dAFQjCNHWPuA87loPNi1WzuPiDihsib1f8g';return tru=
e;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F=
%2Fgodbolt.org%2Fg%2FFMo62c\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHWPuA87=
loPNi1WzuPiDihsib1f8g';return true;">Here's a reduced Godbolt</a>=
=C2=A0with the two swap functions side-by-side.=C2=A0 Indeed, that is very =
cool!</div><div>I admit that, as far as I know, P1144 cannot do that for st=
d::list.</div><div><br></div></div></div></div></blockquote><div><br></div>=
<div>Thank you for this size-by-size view. I should really learn how to use=
all those feature from compiler explorer.<br></div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"=
gmail_quote"><div></div><div><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:sol=
id;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><s=
pan><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,20=
4);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-=
width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><div>Basically, when you say "relocatable=
", you just say "movable", and only trivially relocatable ha=
s a special meaning. That's not something I find useful.</div></div></b=
lockquote><div><br></div><div>But I find it useful, mainly for vector::resi=
ze (which is really just standardizing existing practice as seen in <a href=
=3D"https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#ob=
ject-relocation" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.hre=
f=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Ffaceboo=
k%2Ffolly%2Fblob%2Fmaster%2Ffolly%2Fdocs%2FFBVector.md%23object-relocation\=
x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFvC1J0BKMgS8e1uQcZOZ70ZQw6PQ';r=
eturn true;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dht=
tps%3A%2F%2Fgithub.com%2Ffacebook%2Ffolly%2Fblob%2Fmaster%2Ffolly%2Fdocs%2F=
FBVector.md%23object-relocation\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFvC=
1J0BKMgS8e1uQcZOZ70ZQw6PQ';return true;">Folly's FBVector</a> and <=
a href=3D"https://github.com/electronicarts/EASTL/blob/84127fd4ac234b24a40e=
a7911d05c85e7ba75120/include/EASTL/deque.h#L1791" rel=3D"nofollow" target=
=3D"_blank" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3=
dhttps%3A%2F%2Fgithub.com%2Felectronicarts%2FEASTL%2Fblob%2F84127fd4ac234b2=
4a40ea7911d05c85e7ba75120%2Finclude%2FEASTL%2Fdeque.h%23L1791\x26sa\x3dD\x2=
6sntz\x3d1\x26usg\x3dAFQjCNFR_YPCDKbNkT7I2UbB3wcAK2oGTw';return true;" =
onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fg=
ithub.com%2Felectronicarts%2FEASTL%2Fblob%2F84127fd4ac234b24a40ea7911d05c85=
e7ba75120%2Finclude%2FEASTL%2Fdeque.h%23L1791\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNFR_YPCDKbNkT7I2UbB3wcAK2oGTw';return true;">EASTL's dequ=
e</a>).</div></div></div></div></blockquote><div><br></div></span><div>That=
's exactly where I think it is not useful: vector::resize could be impl=
emented with std::realloc for relocatable types, even if relocation is not =
trivial (see my godbolt implementation above).</div><div>But std::realloc c=
annot work with move+destroy.<br></div><span><div></div></span></div></bloc=
kquote><div><br></div><div>Right. If our goal is to reallocate an array of =
`std::list` objects, then=C2=A0your scheme can use "serialize in a loo=
p + realloc + deserialize in a loop."</div><div>P1144 cannot possibly =
use realloc in that scenario, and must fall back to "malloc + (move+de=
stroy) in a loop + free."</div><div><br></div><div>This applies to `st=
d::list` because it is non-trivially relocatable. To reallocate an array of=
`std::deque` objects, your scheme would use "serialize in a loop + re=
alloc + deserialize in a loop" and mine would use "(unbless?) + r=
ealloc + (bless?)," i.e., we'd be equivalent.</div></div></div></d=
iv></blockquote><div><br></div><div>Yes. Basically, the two are equivalent =
for all trivially relocatable types (for which, we have compatible definiti=
ons).<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>(Ped=
antic note that in practice, `<b>std</b>::vector` cannot possibly use `real=
loc` because it must behave as-if it were using `allocator_traits::allocate=
` and `allocator_traits::deallocate`<wbr>. To actually make it use `realloc=
` you'd first have to make an allocator type that used `malloc` and `fr=
ee` instead of `operator new` and `operator delete`, and then you'd hav=
e to teach `std::vector` about that allocator type as a special case. But I=
can certainly imagine a nonstd::vector =E2=80=94 either non-allocator-awar=
e, or allocator-aware using a richer allocator model than the standard C++1=
7 allocator model =E2=80=94 that would want the ability to do this optimiza=
tion. Also, even if we don't permit `realloc`, your scheme still does</=
div><div>=C2=A0 =C2=A0 allocate + serialize in a loop + memcpy + deserializ=
e in a loop + deallocate</div><div>whereas P1144 does</div><div>=C2=A0 =C2=
=A0 allocate + (move+destroy) in a loop + deallocate<br></div><div>.)</div>=
</div></div></div></blockquote><div><br></div><div>I know all of that. Actu=
ally, that's where I started to think about relocation in the first pla=
ce.</div><div>I might write some stuff about memory allocations in the futu=
r.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1=
px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:=
1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-l=
eft-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><div>I would also find this serialize/deserialize mechan=
ism useful, <i><b>if</b></i> it could be used in the way you apparently env=
ision for it to be used, to "wormhole" position-independent objec=
t representations across process boundaries or from page to page without a =
physical memcpy operation.=C2=A0 Unfortunately, as I said, position-indepen=
dence is a property of a whole region of memory; it's not a property of=
an individual typed object.</div></div></div></div></blockquote><div><br><=
/div></span><div>I agree for interprocess communication. But I'm not co=
nvinced if we stay within the bounds of our program. std:realloc is this ki=
nd of wormhole.</div></div></blockquote><div><br></div><div>Agreed. So &quo=
t;reallocate an array of `std::list` objects" becomes the killer app f=
or the serialize+deserialize approach?=C2=A0 And we haven't made any pa=
rticular progress on the interprocess case?</div><div><br></div><div>=E2=80=
=93Arthur</div></div></div></div></blockquote><div><br></div><div>Yes, that=
would be it. To be fair, I think that's already quite good.</div><div>=
<br></div><div>Also, I have the impression that my proposal is a step forwa=
rd to standardize interprocess communication despite saying nothing about i=
t.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5c5b1132-fd6a-46cb-939c-8eb8d7e26a47%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5c5b1132-fd6a-46cb-939c-8eb8d7e26a47=
%40isocpp.org</a>.<br />
------=_Part_1902_1825704649.1534234284058--
------=_Part_1901_1190175759.1534234284056--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Tue, 14 Aug 2018 01:23:32 -0700 (PDT)
Raw View
------=_Part_1791_1666168527.1534235013033
Content-Type: multipart/alternative;
boundary="----=_Part_1792_459591323.1534235013033"
------=_Part_1792_459591323.1534235013033
Content-Type: text/plain; charset="UTF-8"
I'm going to copy and paste my response on SG14 on a similar topic of
discussion rather than paraphrase myself.
--- cut ---
I'll tell you where I've reached.
I find this whole situation far too vague, hand wavy, and underspecified.
Everybody is using their own imprecise terminology, because there is no
common vocabulary. This leads to lots of non-productive discussion without
much progress.
I find P0593 insufficient to solving the real problem. Back during the
Rapperswil SG12 meeting, it seemed to me that everybody in the room apart
from me felt it closed enough UB that it was good, and it was approved.
And, for the mission statement of SG12 which is to fix problematic UB, then
yes it does indeed solve that one limited problem. But I think it's solving
the *wrong* problem. The real problem is that lifetime and the object model
doesn't have a formal vocabulary to describe it. So the standard basically
is a collection of UB fudges to account for variations in compiler design
and implementation, mixed in with a lot of incremental evolution over
multiple iterations rather than refactoring it afresh.
What I think needs to happen is that somebody needs to sit down, trawl
through the source code of clang, and come up with a vocabulary describing
the lifetime stages of the C++ object model from the perspective of the
clang C++ compiler.
Once we have that vocabulary, we can start discussing this stuff from a
common hymm sheet, instead of this current pontificating.
I don't have time to write said common hymm sheet before San Diego. So many
spinning plates already. Hence I'll be kicking the LLFIO object model stuff
down the road. But if somebody else wants to do one up, and submit it as a
paper for San Diego, I think it would be *enormously* valuable to everybody
moving forwards.
Niall
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d51a6619-b8cb-474a-b81e-9be13a8a9d7e%40isocpp.org.
------=_Part_1792_459591323.1534235013033
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'm going to copy and paste my response on SG14 on a s=
imilar topic of discussion rather than paraphrase myself.<div><br></div><di=
v>--- cut ---</div><div><br></div><div><div>I'll tell you where I'v=
e reached.</div><div><br></div><div>I find this whole situation far too vag=
ue, hand wavy, and underspecified. Everybody is using their own imprecise t=
erminology, because there is no common vocabulary. This leads to lots of no=
n-productive discussion without much progress.</div><div><br></div><div>I f=
ind P0593 insufficient to solving the real problem. Back during the Rappers=
wil SG12 meeting, it seemed to me that everybody in the room apart from me =
felt it closed enough UB that it was good, and it was approved. And, for th=
e mission statement of SG12 which is to fix problematic UB, then yes it doe=
s indeed solve that one limited problem. But I think it's solving the=
=C2=A0<i>wrong</i>=C2=A0problem. The real problem is that lifetime and the =
object model doesn't have a formal vocabulary to describe it. So the st=
andard basically is a collection of UB fudges to account for variations in =
compiler design and implementation, mixed in with a lot of incremental evol=
ution over multiple iterations rather than refactoring it afresh.</div><div=
><br></div><div>What I think needs to happen is that somebody needs to sit =
down, trawl through the source code of clang, and come up with a vocabulary=
describing the lifetime stages of the C++ object model from the perspectiv=
e of the clang C++ compiler.</div><div><br></div><div>Once we have that voc=
abulary, we can start discussing this stuff from a common hymm sheet, inste=
ad of this current pontificating.</div><div><br></div><div>I don't have=
time to write said common hymm sheet before San Diego. So many spinning pl=
ates already. Hence I'll be kicking the LLFIO object model stuff down t=
he road. But if somebody else wants to do one up, and submit it as a paper =
for San Diego, I think it would be=C2=A0<b>enormously</b>=C2=A0valuable to =
everybody moving forwards.</div><div><br></div><div>Niall</div></div><div><=
br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d51a6619-b8cb-474a-b81e-9be13a8a9d7e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d51a6619-b8cb-474a-b81e-9be13a8a9d7e=
%40isocpp.org</a>.<br />
------=_Part_1792_459591323.1534235013033--
------=_Part_1791_1666168527.1534235013033--
.
Author: florian.csdt@gmail.com
Date: Tue, 14 Aug 2018 01:48:23 -0700 (PDT)
Raw View
------=_Part_1787_1019133993.1534236503327
Content-Type: multipart/alternative;
boundary="----=_Part_1788_379930786.1534236503327"
------=_Part_1788_379930786.1534236503327
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 14 ao=C3=BBt 2018 10:23:33 UTC+2, Niall Douglas a =C3=A9crit :
>
> I'm going to copy and paste my response on SG14 on a similar topic of=20
> discussion rather than paraphrase myself.
>
> --- cut ---
>
> I'll tell you where I've reached.
>
> I find this whole situation far too vague, hand wavy, and underspecified.=
=20
> Everybody is using their own imprecise terminology, because there is no=
=20
> common vocabulary. This leads to lots of non-productive discussion withou=
t=20
> much progress.
>
> I find P0593 insufficient to solving the real problem. Back during the=20
> Rapperswil SG12 meeting, it seemed to me that everybody in the room apart=
=20
> from me felt it closed enough UB that it was good, and it was approved.=
=20
> And, for the mission statement of SG12 which is to fix problematic UB, th=
en=20
> yes it does indeed solve that one limited problem. But I think it's solvi=
ng=20
> the *wrong* problem. The real problem is that lifetime and the object=20
> model doesn't have a formal vocabulary to describe it. So the standard=20
> basically is a collection of UB fudges to account for variations in=20
> compiler design and implementation, mixed in with a lot of incremental=20
> evolution over multiple iterations rather than refactoring it afresh.
>
> What I think needs to happen is that somebody needs to sit down, trawl=20
> through the source code of clang, and come up with a vocabulary describin=
g=20
> the lifetime stages of the C++ object model from the perspective of the=
=20
> clang C++ compiler.
>
> Once we have that vocabulary, we can start discussing this stuff from a=
=20
> common hymm sheet, instead of this current pontificating.
>
> I don't have time to write said common hymm sheet before San Diego. So=20
> many spinning plates already. Hence I'll be kicking the LLFIO object mode=
l=20
> stuff down the road. But if somebody else wants to do one up, and submit =
it=20
> as a paper for San Diego, I think it would be *enormously* valuable to=20
> everybody moving forwards.
>
> Niall
>
>
That's exactly why I built my proposal from scratch to define relocation,=
=20
and make it part of the language as core feature, and not a patchwork above=
=20
the rest.
It's a bottom-up approach: define the base bricks, and use them to build=20
the language.
It's most likely not enough for you, but at least I tried.
My approach tries to limit as much as possible those UB. But as soon as IPC=
=20
kicks in, I have no choice (I'm not expert enough to propose something=20
useful about IPC).
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/80de22c4-3a25-4b12-b7b3-8338ee3a8247%40isocpp.or=
g.
------=_Part_1788_379930786.1534236503327
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 14 ao=C3=BBt 2018 10:23:33 UTC+2, Niall D=
ouglas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr">I'm going to copy and paste my response on SG14 on a simil=
ar topic of discussion rather than paraphrase myself.<div><br></div><div>--=
- cut ---</div><div><br></div><div><div>I'll tell you where I've re=
ached.</div><div><br></div><div>I find this whole situation far too vague, =
hand wavy, and underspecified. Everybody is using their own imprecise termi=
nology, because there is no common vocabulary. This leads to lots of non-pr=
oductive discussion without much progress.</div><div><br></div><div>I find =
P0593 insufficient to solving the real problem. Back during the Rapperswil =
SG12 meeting, it seemed to me that everybody in the room apart from me felt=
it closed enough UB that it was good, and it was approved. And, for the mi=
ssion statement of SG12 which is to fix problematic UB, then yes it does in=
deed solve that one limited problem. But I think it's solving the=C2=A0=
<i>wrong</i>=C2=A0problem. The real problem is that lifetime and the object=
model doesn't have a formal vocabulary to describe it. So the standard=
basically is a collection of UB fudges to account for variations in compil=
er design and implementation, mixed in with a lot of incremental evolution =
over multiple iterations rather than refactoring it afresh.</div><div><br><=
/div><div>What I think needs to happen is that somebody needs to sit down, =
trawl through the source code of clang, and come up with a vocabulary descr=
ibing the lifetime stages of the C++ object model from the perspective of t=
he clang C++ compiler.</div><div><br></div><div>Once we have that vocabular=
y, we can start discussing this stuff from a common hymm sheet, instead of =
this current pontificating.</div><div><br></div><div>I don't have time =
to write said common hymm sheet before San Diego. So many spinning plates a=
lready. Hence I'll be kicking the LLFIO object model stuff down the roa=
d. But if somebody else wants to do one up, and submit it as a paper for Sa=
n Diego, I think it would be=C2=A0<b>enormously</b>=C2=A0valuable to everyb=
ody moving forwards.</div><div><br></div><div>Niall</div></div><div><br></d=
iv></div></blockquote><div><br></div><div>That's exactly why I built my=
proposal from scratch to define relocation, and make it part of the langua=
ge as core feature, and not a patchwork above the rest.</div><div>It's =
a bottom-up approach: define the base bricks, and use them to build the lan=
guage.<br></div><div>It's most likely not enough for you, but at least =
I tried.</div><div><br></div><div>My approach tries to limit as much as pos=
sible those UB. But as soon as IPC kicks in, I have no choice (I'm not =
expert enough to propose something useful about IPC).</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/80de22c4-3a25-4b12-b7b3-8338ee3a8247%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/80de22c4-3a25-4b12-b7b3-8338ee3a8247=
%40isocpp.org</a>.<br />
------=_Part_1788_379930786.1534236503327--
------=_Part_1787_1019133993.1534236503327--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Tue, 14 Aug 2018 01:54:53 -0700 (PDT)
Raw View
------=_Part_1854_966140536.1534236893810
Content-Type: multipart/alternative;
boundary="----=_Part_1855_1137589464.1534236893810"
------=_Part_1855_1137589464.1534236893810
Content-Type: text/plain; charset="UTF-8"
>
> That's exactly why I built my proposal from scratch to define relocation,
> and make it part of the language as core feature, and not a patchwork above
> the rest.
> It's a bottom-up approach: define the base bricks, and use them to build
> the language.
> It's most likely not enough for you, but at least I tried.
>
> My approach tries to limit as much as possible those UB. But as soon as
> IPC kicks in, I have no choice (I'm not expert enough to propose something
> useful about IPC).
>
You've completely missed the point.
We're all inventing a vocabulary here. It's not productive. We need to stop
doing that.
Somebody needs to go study a real compiler and generate a vocabulary which
that real compiler itself uses internally. Otherwise we are wasting effort.
Niall
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6fda45cd-1409-4247-97bf-f36ee40ee9b2%40isocpp.org.
------=_Part_1855_1137589464.1534236893810
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>That's exactly why I built my proposal from scratch to define =
relocation, and make it part of the language as core feature, and not a pat=
chwork above the rest.</div><div>It's a bottom-up approach: define the =
base bricks, and use them to build the language.<br></div><div>It's mos=
t likely not enough for you, but at least I tried.</div><div><br></div><div=
>My approach tries to limit as much as possible those UB. But as soon as IP=
C kicks in, I have no choice (I'm not expert enough to propose somethin=
g useful about IPC).</div></div></blockquote><div><br></div><div>You've=
completely missed the point.</div><div><br></div><div>We're all invent=
ing a vocabulary here. It's not productive. We need to stop doing that.=
</div><div><br></div><div>Somebody needs to go study a real compiler and ge=
nerate a vocabulary which that real compiler itself uses internally.=C2=A0 =
Otherwise we are wasting effort.</div><div><br></div><div>Niall</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6fda45cd-1409-4247-97bf-f36ee40ee9b2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6fda45cd-1409-4247-97bf-f36ee40ee9b2=
%40isocpp.org</a>.<br />
------=_Part_1855_1137589464.1534236893810--
------=_Part_1854_966140536.1534236893810--
.
Author: florian.csdt@gmail.com
Date: Tue, 14 Aug 2018 02:09:14 -0700 (PDT)
Raw View
------=_Part_1722_807094698.1534237754566
Content-Type: multipart/alternative;
boundary="----=_Part_1723_582983710.1534237754566"
------=_Part_1723_582983710.1534237754566
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 14 ao=C3=BBt 2018 10:54:53 UTC+2, Niall Douglas a =C3=A9crit :
>
> That's exactly why I built my proposal from scratch to define relocation,=
=20
>> and make it part of the language as core feature, and not a patchwork ab=
ove=20
>> the rest.
>> It's a bottom-up approach: define the base bricks, and use them to build=
=20
>> the language.
>> It's most likely not enough for you, but at least I tried.
>>
>> My approach tries to limit as much as possible those UB. But as soon as=
=20
>> IPC kicks in, I have no choice (I'm not expert enough to propose somethi=
ng=20
>> useful about IPC).
>>
>
> You've completely missed the point.
>
Out of any context, your point was difficult to guess.
> We're all inventing a vocabulary here. It's not productive. We need to=20
> stop doing that.
>
>
For me, the only way to standardize a term is to standardize the feature=20
related to the term. Otherwise, the term might end up with a definition off=
=20
compared to what the feature will need.
And the only way I see to do that, is to invent some vocabulary terms for=
=20
each proposal.
The goal is then to converge on the term used and its definition. But than=
=20
cannot be done upfront!
=20
> Somebody needs to go study a real compiler and generate a vocabulary whic=
h=20
> that real compiler itself uses internally. Otherwise we are wasting effo=
rt.
>
I'm speculating here, but I think that compiler devs don't agree on most of=
=20
those terms neither.
Scientific papers might be a good source for that (because of the=20
scientific consensus), but I doubt there are many papers on this particular=
=20
subject.
=20
>
> Niall
>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/62ee3367-579f-411f-a80e-372aad4d3f5e%40isocpp.or=
g.
------=_Part_1723_582983710.1534237754566
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 14 ao=C3=BBt 2018 10:54:53 UTC+2, Niall D=
ouglas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=
That's exactly why I built my proposal from scratch to define relocatio=
n, and make it part of the language as core feature, and not a patchwork ab=
ove the rest.</div><div>It's a bottom-up approach: define the base bric=
ks, and use them to build the language.<br></div><div>It's most likely =
not enough for you, but at least I tried.</div><div><br></div><div>My appro=
ach tries to limit as much as possible those UB. But as soon as IPC kicks i=
n, I have no choice (I'm not expert enough to propose something useful =
about IPC).</div></div></blockquote><div><br></div><div>You've complete=
ly missed the point.</div></div></blockquote><div><br></div><div>Out of any=
context, your point was difficult to guess.<br></div><div><br></div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div=
>We're all inventing a vocabulary here. It's not productive. We nee=
d to stop doing that.</div><div><br></div></div></blockquote><br><div></div=
><div>For me, the only way to standardize a term is to standardize the feat=
ure related to the term. Otherwise, the term might end up with a definition=
off compared to what the feature will need.</div><div>And the only way I s=
ee to do that, is to invent some vocabulary terms for each proposal.</div><=
div>The goal is then to converge on the term used and its definition. But t=
han cannot be done upfront!<br></div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>Somebody needs to =
go study a real compiler and generate a vocabulary which that real compiler=
itself uses internally.=C2=A0 Otherwise we are wasting effort.</div></div>=
</blockquote><div><div><br></div><div>I'm speculating here, but I think=
that compiler devs don't agree on most of those terms neither.</div><d=
iv>Scientific papers might be a good source for that (because of the scient=
ific consensus), but I doubt there are many papers on this particular subje=
ct.<br></div></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><br></div><div>Niall</div></div></blockquote></=
div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62ee3367-579f-411f-a80e-372aad4d3f5e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/62ee3367-579f-411f-a80e-372aad4d3f5e=
%40isocpp.org</a>.<br />
------=_Part_1723_582983710.1534237754566--
------=_Part_1722_807094698.1534237754566--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Tue, 14 Aug 2018 10:57:46 -0700
Raw View
--000000000000978fb3057368f269
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tue, Aug 14, 2018 at 1:11 AM, <florian.csdt@gmail.com> wrote:
> Le mardi 14 ao=C3=BBt 2018 01:37:19 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>
>> On Mon, Aug 13, 2018 at 3:11 PM, <floria...@gmail.com> wrote:
>>
>>> Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit =
:
>>>>
>>>> On Mon, Aug 13, 2018 at 2:52 AM, <floria...@gmail.com> wrote:
>>>>
>>>>>
>>>>> You seem to want all movable types to also be relocatable by saying:
>>>>> if a type is not trivially relocatable, then relocate =3D memcpy + de=
stroy.
>>>>> What I propose is that some types will not be relocatable at all (mor=
e
>>>>> on this later). And the fallback is written by the user because it hi=
ghly
>>>>> depends on where relocation is used.
>>>>> For instance, there is no way to emulate serialize+realloc+deserializ=
e
>>>>> with your form of fallback.
>>>>> As I don't provide any automatic fallback at the language level, the
>>>>> user (might be a library writer) will need to write the fallback code
>>>>> themselves (here: allocate+move+destroy+deallocate).
>>>>>
>>>>> So when you say "in my design, T is relocatable", I will now
>>>>> understand: "T is movable and non relocatable; serialize+memcpy+deser=
ialize
>>>>> could be emulated by move+destroy".
>>>>> But I fail to see what you gain from this.
>>>>>
>>>>
>>>> Our definitions are converging! This is good news. :)
>>>>
>>>> I am not too worried that you fail to see what we gain from P1144's
>>>> definition of relocation (over yours), because vice versa I fail to se=
e
>>>> what we gain from your definition of relocation (over P1144's). I thi=
nk
>>>> that as we plug the holes in your definition, it is quickly converging=
to
>>>> *almost* the same thing as P1144; therefore both definitions have just
>>>> about the same advantages and disadvantages. The only thing I would to=
ut as
>>>> a remaining major advantage of P1144 is that it has a proposal with wo=
rding
>>>> and a complete implementation on Godbolt =E2=80=94 and I will happily =
admit that
>>>> this is purely circumstantial and does not necessarily indicate that y=
ours
>>>> *couldn't* have such an implementation (now that most of the holes are
>>>> plugged).
>>>>
>>>
>>> As I said quite a while ago, our two proposals are not mutually
>>> exclusive. It is possible to modify slightly yours to let the possibili=
ty
>>> to standardize mine.
>>> The only modification really necessary would be:
>>> template <class T> concept Relocatable =3D NothrowRelocatable<T>;
>>> template <class T> concept NothrowRelocatable =3D TriviallyRelocatable<=
T>;
>>> instead of:
>>> template <class T> concept Relocatable =3D MoveConstructible<T> &&
>>> Destructible<T>;
>>> template <class T> concept NothrowRelocatable =3D NothrowMoveConstructi=
ble
>>> <T> && NothrowDestructible<T>;
>>>
>>
>> I don't quite see what the former two lines are doing. You want things t=
o
>> be Relocatable iff they are TriviallyRelocatable? But what about things
>> that are "relocatable but non-trivially so"? In P1144, that would be
>> anything with a user-defined move-ctor and dtor; in your scheme, that wo=
uld
>> be anything with a user-defined `serialize` and `deserialize`.
>>
>> I think pursuing this line might confuse both of us even more, so I'd be
>> happy to drop it. :P
>>
>
> Basically, the latter is what you have in your proposal currently.
> And the former is what I propose for your proposal to be completely
> forward compatible with mine.
>
> Because widening a contract is easy, but narrowing is almost impossible.
>
As I understand it, your scheme as proposed "for the near future" looks
like this:
- Any type with a trivial move-constructor and a trivial destructor is
"trivially relocatable."
- Any type with a non-trivial move-constructor and/or a non-trivial
destructor is "not relocatable."
- Any type with no move-constructor and/or no destructor is "not
relocatable."
- vector, swap, etc., can be optimized to use memcpy only for "trivially
relocatable" types as described above, and fall back to move+destroy.
And for the "far future", it looks like this:
- Any type with a trivial move-constructor and a trivial destructor will
gain implicitly defaulted serialize/deserialize operators.
- Any type with trivial serialize/deserialize operators is "trivially
relocatable."
- Any type with (non-trivial) serialize/deserialize operators is
"relocatable."
- Any type with no serialize/deserialize operators is "not relocatable."
- vector, swap, etc., can be optimized to use memcpy only for "relocatable"
types as described above, and fall back to move+destroy.
I'm sure I'm not describing the bullet points in exactly the same order or
with the same relative emphasis as you would... but is this a reasonably
accurate summary of your "far future" proposal and the "completely forward
compatible" ("near future") subset that you're talking about w.r.t. P1144?
Actually, a more argumentative-sounding set of bullet points for your "far
future" proposal would be
- Any type with a trivial move-constructor and a trivial destructor will
gain implicitly defaulted serialize/deserialize operators.
- Any type with trivial serialize/deserialize operators (even if it has no
move-constructor and/or no destructor) is "trivially relocatable."
- Any type with (non-trivial) serialize/deserialize operators (even if it
has no move-constructor and/or no destructor) is "relocatable."
- Any type with no serialize/deserialize operators is "not relocatable."
- vector, swap, etc., can be optimized to use memcpy only for
"move-constructible, destructible, relocatable" types as described above,
and fall back to move+destroy.
Right? Because I think you wouldn't propose to change the constraints on
vector, swap, etc., so move-constructibility and destructibility would
still be required by their constraints?
[...]
> Two messages ago, I understood you as wanting the following `One` to be
>> trivially relocatable.
>>
>> struct One {
>> std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially
>> relocatable, or perhaps nonrelocatable
>> offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or
>> perhaps nonrelocatable
>>
>> // Warrant that "One" happens to be trivially relocatable for our
>> purposes, even though its individual members are not trivially relocatab=
le
>> operator serialize() =3D default;
>> operator deserialize() =3D default;
>> };
>>
>
> You convinced me that an offset_ptr shouldn't be relocatable, so let be i=
t
> (which is the default anyway as offset_ptr move constructor is not trivia=
l).
> One will then "inherits" the non-relocalibility from offset_ptr.
>
Okay, good. Agreed. And agreed that the user could provide a user-provided
`operator serialize() {}` to get non-trivial-but-still-no-op serialization
if that's what they wanted.
That's the idea. Here, to solve this minor issue, your attribute might come
> handy.
>
Now here's our last major beef:
[...]
> Also, I have the impression that my proposal is a step forward to
> standardize interprocess communication despite saying nothing about it.
>
> I am strongly of the opinion that your proposal does *nothing* in the
direction of standardizing interprocess communication; in fact it is worse
than nothing, because it claims the words "serialize" and "deserialize" for
operations that fundamentally *cannot possibly work* unless the address
space is shared. (E.g., your `std::list` example.)
I do not know what "serialize" ought to mean, specifically, in the
Standard, but I am confident that what human programmers mean by it is very
context-dependent. Your proposal works well for "serializing" something in
preparation for a memcpy (or memcpy-alike, such as realloc), but it does
not and cannot work for "serializing" something in preparation for
transmission over a network, or sharing into a different address space.
Your proposal places "serialize" in the context of a type, such as
std::list, but that is not good enough, because there are many different
ways of serializing a std::list. Which way is correct depends on more
context than just the type itself.
Could you fix this by adding a "context" parameter, like `operator
serialize(std::serialization_kind =3D std::serialization_kind::in_process)`=
?
Maybe. I wouldn't confidently say "no." But I wouldn't say "yes" either.
I'd want to see some effort to actually work it out and use the scheme in
practice and show that it works for someone's use-case somewhere in the
world.
The Folly/EASTL/P1144 definition of "relocatable" (which is also the BSL/Qt
"moveable") has been shown to work for someone's use-case in practice.
That's why I'm comfortable with the idea of standardizing both the
technique and the vocabulary we use to describe it. As far as I am aware,
nobody has ever tried this "serialize-in-place/memcpy/deserialize" idea in
practice (which is a minor red flag), and I believe it is claiming very
valuable *new* real estate in a way that fundamentally *cannot possibly
work* for future use-cases.
(That said, I have had a real hard time getting any engagement from the
Folly or BSL people, and I have shamefully not yet reached out to EA. I'll
go write that email today. It is possible that they all ended up being
unhappy with their concept of "relocatable," or found it was less important
in a move-semantics world than it had been in C++03.)
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0%2BCvdEhy1wANcNHqx%3DPWg3umBuBeRUHOTc1rJq=
7T0n6kg%40mail.gmail.com.
--000000000000978fb3057368f269
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tue, Aug 14, 2018 at 1:11 AM, <span dir=3D"ltr"><<a=
href=3D"mailto:florian.csdt@gmail.com" target=3D"_blank">florian.csdt@gmai=
l.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,=
204,204);padding-left:1ex"><div dir=3D"ltr">Le mardi 14 ao=C3=BBt 2018 01:3=
7:19 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span class=3D"gmail-"><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pad=
ding-left:1ex"><div dir=3D"ltr">On Mon, Aug 13, 2018 at 3:11 PM, <span dir=
=3D"ltr"><<a rel=3D"nofollow">floria...@gmail.com</a>></span> wrote:<=
div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;borde=
r-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Le lundi 1=
3 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit=C2=A0:<spa=
n><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204)=
;padding-left:1ex"><div dir=3D"ltr">On Mon, Aug 13, 2018 at 2:52 AM, <span=
dir=3D"ltr"><<a rel=3D"nofollow">floria...@gmail.com</a>></span> wro=
te:<br><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:sol=
id;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><b=
r>You seem to want all movable types to also be relocatable by saying: if a=
type is not trivially relocatable, then relocate =3D memcpy + destroy.<br>=
What I propose is that some types will not be relocatable at all (more on t=
his later). And the fallback is written by the user because it highly depen=
ds on where relocation is used.<br>For instance, there is no way to emulate=
serialize+realloc+deserialize with your form of fallback.<br>As I don'=
t provide any automatic fallback at the language level, the user (might be =
a library writer) will need to write the fallback code themselves (here: al=
locate+move+destroy+dealloca<wbr>te).<br><br>So when you say "in my de=
sign, T is relocatable", I will now understand: "T is movable and=
non relocatable; serialize+memcpy+deserialize could be emulated by move+de=
stroy".<br>But I fail to see what you gain from this.<br></div></block=
quote><div><br></div><div>Our definitions are converging!=C2=A0 This is goo=
d news. :)</div><div><br></div><div>I am not too worried that you fail to s=
ee what we gain from P1144's definition of relocation (over yours), bec=
ause vice versa I fail to see what we gain from your definition of relocati=
on (over P1144's).=C2=A0 I think that as we plug the holes in your defi=
nition, it is quickly converging to <i>almost</i> the same thing as P1144; =
therefore both definitions have just about the same advantages and disadvan=
tages. The only thing I would tout as a remaining major advantage of P1144 =
is that it has a proposal with wording and a complete implementation on God=
bolt =E2=80=94 and I will happily admit that this is purely circumstantial =
and does not necessarily indicate that yours <i>couldn't</i> have such =
an implementation (now that most of the holes are plugged).</div></div></di=
v></div></blockquote><div><br></div></span><div>As I said quite a while ago=
, our two proposals are not mutually exclusive. It is possible to modify sl=
ightly yours to let the possibility to standardize mine.</div><div>The only=
modification really necessary would be:</div><div><div style=3D"background=
-color:rgb(250,250,250);border:1px solid rgb(187,187,187)"><code><div><span=
style=3D"color:rgb(0,0,136)">template</span><span style=3D"color:rgb(0,0,0=
)"> </span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"c=
olor:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0,0)"> T</span><s=
pan style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(0,0,136)">concept</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Relocatable=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(10=
2,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(102,0,102)">NothrowRelocatable</span><span style=3D"color:rgb(10=
2,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span style=
=3D"color:rgb(102,102,0)">>;</span><span style=3D"color:rgb(0,0,0)"><br>=
</span><span style=3D"color:rgb(0,0,136)">template</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</span><spa=
n style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0,0)"=
> T</span><span style=3D"color:rgb(102,102,0)">></span><span style=3D"co=
lor:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">concept</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)"=
>NothrowRelocatable</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,0,102)">TriviallyRelocatable</span><span =
style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">=
T</span><span style=3D"color:rgb(102,102,0)">>;</span><span style=3D"col=
or:rgb(0,0,0)"><br></span></div></code></div>instead of:</div><div><div sty=
le=3D"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187)">=
<code><div><span style=3D"color:rgb(0,0,136)">template</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</span>=
<span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0=
,0)"> T</span><span style=3D"color:rgb(102,102,0)">></span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">concept</s=
pan><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0=
,102)">Relocatable</span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(102,0,102)">MoveConstructible</span><span styl=
e=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</s=
pan><span style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">&&</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">=
Destructible</span><span style=3D"color:rgb(102,102,0)"><</span><span st=
yle=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">>;=
</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb=
(0,0,136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">=
class</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:=
rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span s=
tyle=3D"color:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)">=
</span><span style=3D"color:rgb(102,0,102)">NothrowRelocatable</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,0,102)">NothrowMoveConstructible</span><span style=3D"color:rgb(102,10=
2,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"co=
lor:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(102,102,0)">&&</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">NothrowDestructible</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">>;</span><span s=
tyle=3D"color:rgb(0,0,0)"><br></span></div></code></div></div></div></block=
quote><div><br></div><div>I don't quite see what the former two lines a=
re doing. You want things to be Relocatable iff they are TriviallyRelocatab=
le? But what about things that are "relocatable but non-trivially so&q=
uot;?=C2=A0 In P1144, that would be anything with a user-defined move-ctor =
and dtor; in your scheme, that would be anything with a user-defined `seria=
lize` and `deserialize`.</div><div><br></div><div>I think pursuing this lin=
e might confuse both of us even more, so I'd be happy to drop it. :P</d=
iv></div></div></div></blockquote><div><br></div></span><div>Basically, the=
latter is what you have in your proposal currently.</div><div>And the form=
er is what I propose for your proposal to be completely forward compatible =
with mine.</div><div><br></div><div>Because widening a contract is easy, bu=
t narrowing is almost impossible.<br></div></div></blockquote><div><br></di=
v><div>As I understand it, your scheme as proposed "for the near futur=
e" looks like this:</div><div>- Any type with a trivial move-construct=
or and a trivial destructor is "trivially relocatable."</div><div=
>- Any type with a non-trivial move-constructor and/or a non-trivial destru=
ctor is "not relocatable."</div><div><div>- Any type with no move=
-constructor and/or no destructor is "not relocatable."</div></di=
v><div>- vector, swap, etc., can be optimized to use memcpy only for "=
trivially relocatable" types as described above, and fall back to move=
+destroy.</div><div><br></div><div>And for the "far future", it l=
ooks like this:</div><div><div>- Any type with a trivial move-constructor a=
nd a trivial destructor will gain implicitly defaulted serialize/deserializ=
e operators.</div><div>- Any type with trivial serialize/deserialize operat=
ors is "trivially relocatable."<br></div><div>- Any type with (no=
n-trivial) serialize/deserialize operators is "relocatable."</div=
><div>- Any type with no serialize/deserialize operators is "not reloc=
atable."</div><div>- vector, swap, etc., can be optimized to use memcp=
y only for "relocatable" types as described above, and fall back =
to move+destroy.</div></div><div><br></div><div>I'm sure I'm not de=
scribing the bullet points in exactly the same order or with the same relat=
ive emphasis as you would... but is this a reasonably accurate summary of y=
our "far future" proposal and the "completely forward compat=
ible" ("near future") subset that you're talking about w=
..r.t. P1144?</div><div><br></div><div><br></div><div>Actually, a more argum=
entative-sounding set of bullet points for your "far future" prop=
osal would be</div><div><div><div>- Any type with a trivial move-constructo=
r and a trivial destructor will gain implicitly defaulted serialize/deseria=
lize operators.</div><div>- Any type with trivial serialize/deserialize ope=
rators (even if it has no move-constructor and/or no destructor) is "t=
rivially relocatable."</div><div>- Any type with (non-trivial) seriali=
ze/deserialize operators (even if it has no move-constructor and/or no dest=
ructor) is "relocatable."</div><div>- Any type with no serialize/=
deserialize operators is "not relocatable."</div><div>- vector, s=
wap, etc., can be optimized to use memcpy only for "move-constructible=
, destructible, relocatable" types as described above, and fall back t=
o move+destroy.</div></div></div><div><br></div><div>Right? Because I think=
you wouldn't propose to change the constraints on vector, swap, etc., =
so move-constructibility and destructibility would still be required by the=
ir constraints?</div><div><br></div><div><br></div><div><br></div><div>[...=
]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204=
,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:=
1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left=
:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Two messages ag=
o, I understood you as wanting the following `One` to be trivially relocata=
ble.</div><div><br></div><div><div><div>struct One {</div><div>=C2=A0 =C2=
=A0 std::vector<int, offset_ptr_allocator<int>> vec; =C2=A0// n=
ontrivially relocatable, or perhaps nonrelocatable</div><div>=C2=A0 =C2=A0 =
offset_ptr<int> ptr_into_vec; =C2=A0// nontrivially relocatable, or p=
erhaps nonrelocatable</div><div><br></div><div>=C2=A0 =C2=A0 // Warrant tha=
t "One" happens to be trivially relocatable for our purposes, eve=
n though its individual members are not trivially relocatable</div><div>=C2=
=A0 =C2=A0 operator serialize() =3D default;</div><div>=C2=A0 =C2=A0 operat=
or deserialize() =3D default;</div><div>};</div></div></div></div></div></d=
iv></blockquote><div><br></div></span><div>You convinced me that an offset_=
ptr shouldn't be relocatable, so let be it (which is the default anyway=
as offset_ptr move constructor is not trivial).</div><div>One will then &q=
uot;inherits" the non-relocalibility from offset_ptr.<br></div></div><=
/blockquote><div><br></div><div>Okay, good. Agreed.=C2=A0 And agreed that t=
he user could provide a user-provided `operator serialize() {}` to get non-=
trivial-but-still-no-op serialization if that's what they wanted.</div>=
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb=
(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>That's the idea. =
Here, to solve this minor issue, your attribute might come handy.<br></div>=
<span class=3D"gmail-"><div></div></span></div></blockquote><div><br></div>=
<div><br></div><div>Now here's our last major beef:</div><div><br></div=
><div>[...]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D"gmail-"><=
div>Also, I have the impression that my proposal is a step forward to stand=
ardize interprocess communication despite saying nothing about it.<br></div=
></span></div><span class=3D"gmail-">
<p></p>
</span></blockquote><div>I am strongly of the opinion that your proposal do=
es <i>nothing</i> in the direction of standardizing interprocess communicat=
ion; in fact it is worse than nothing, because it claims the words "se=
rialize" and "deserialize" for operations that fundamentally=
<i>cannot possibly work</i> unless the address space is shared. (E.g., you=
r `std::list` example.)</div><div>I do not know what "serialize" =
ought to mean, specifically, in the Standard, but I am confident that what =
human programmers mean by it is very context-dependent. Your proposal works=
well for "serializing" something in preparation for a memcpy (or=
memcpy-alike, such as realloc), but it does not and cannot work for "=
serializing" something in preparation for transmission over a network,=
or sharing into a different address space. Your proposal places "seri=
alize" in the context of a type, such as std::list, but that is not go=
od enough, because there are many different ways of serializing a std::list=
.. Which way is correct depends on more context than just the type itself.</=
div><div>Could you fix this by adding a "context" parameter, like=
`operator serialize(std::serialization_kind =3D std::serialization_kind::i=
n_process)`?=C2=A0 Maybe. I wouldn't confidently say "no." =
=C2=A0But I wouldn't say "yes" either. I'd want to see so=
me effort to actually work it out and use the scheme in practice and show t=
hat it works for someone's use-case somewhere in the world.</div><div>T=
he Folly/EASTL/P1144 definition of "relocatable" (which is also t=
he BSL/Qt "moveable") has been shown to work for someone's us=
e-case in practice. That's why I'm comfortable with the idea of sta=
ndardizing both the technique and the vocabulary we use to describe it.=C2=
=A0 As far as I am aware, nobody has ever tried this "serialize-in-pla=
ce/memcpy/deserialize" idea in practice (which is a minor red flag), a=
nd I believe it is claiming very valuable <i>new</i> real estate in a way t=
hat fundamentally <i>cannot possibly work</i> for future use-cases. =C2=A0<=
/div><div><br></div><div>(That said, I have had a real hard time getting an=
y engagement from the Folly or BSL people, and I have shamefully not yet re=
ached out to EA. I'll go write that email today. It is possible that th=
ey all ended up being unhappy with their concept of "relocatable,"=
; or found it was less important in a move-semantics world than it had been=
in C++03.)</div><div><br></div><div>=E2=80=93Arthur</div></div></div></div=
>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2BCvdEhy1wANcNHqx%3DPWg3umBuB=
eRUHOTc1rJq7T0n6kg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0%2BCvd=
Ehy1wANcNHqx%3DPWg3umBuBeRUHOTc1rJq7T0n6kg%40mail.gmail.com</a>.<br />
--000000000000978fb3057368f269--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Tue, 14 Aug 2018 11:04:09 -0700
Raw View
--00000000000073f90005736909ca
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tue, Aug 14, 2018 at 1:54 AM, Niall Douglas <nialldouglas14@gmail.com>
wrote:
> That's exactly why I built my proposal from scratch to define relocation,
>> and make it part of the language as core feature, and not a patchwork ab=
ove
>> the rest.
>> It's a bottom-up approach: define the base bricks, and use them to build
>> the language.
>> It's most likely not enough for you, but at least I tried.
>>
>> My approach tries to limit as much as possible those UB. But as soon as
>> IPC kicks in, I have no choice (I'm not expert enough to propose somethi=
ng
>> useful about IPC).
>>
>
> You've completely missed the point.
>
> We're all inventing a vocabulary here. It's not productive. We need to
> stop doing that.
>
> Somebody needs to go study a real compiler and generate a vocabulary whic=
h
> that real compiler itself uses internally. Otherwise we are wasting effo=
rt.
>
Niall, can you elaborate on this point, and in particular how
https://github.com/Quuxplusone/clang/commit/f755170d59c7b70d9f8358a79cc05a5=
eeb74f92f
https://reviews.llvm.org/D50119
would not count as steps in that direction? (See also D49317
<https://reviews.llvm.org/D49317>.)
Niall, if there's a specific operation that you'd like to know the name of,
if you can describe it unambiguously, I volunteer to go find out what (if
anything) Clang calls it.
What makes that tricky (AFAICT) is that mostly in this thread we've been
discussing operations that do not exist in the Standard... so of course
they don't exist in most compilers, either.
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CADvuK0Jnh7FjVKiaFqXEVCVEN%2Bbo9opetgNDqnuDtonMq=
OV22A%40mail.gmail.com.
--00000000000073f90005736909ca
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tue, Aug 14, 2018 at 1:54 AM, Niall Douglas <span dir=
=3D"ltr"><<a href=3D"mailto:nialldouglas14@gmail.com" target=3D"_blank">=
nialldouglas14@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra=
"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-=
left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span class=
=3D"gmail-"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(20=
4,204,204);padding-left:1ex"><div dir=3D"ltr"><div>That's exactly why I=
built my proposal from scratch to define relocation, and make it part of t=
he language as core feature, and not a patchwork above the rest.</div><div>=
It's a bottom-up approach: define the base bricks, and use them to buil=
d the language.<br></div><div>It's most likely not enough for you, but =
at least I tried.</div><div><br></div><div>My approach tries to limit as mu=
ch as possible those UB. But as soon as IPC kicks in, I have no choice (I&#=
39;m not expert enough to propose something useful about IPC).</div></div><=
/blockquote><div><br></div></span><div>You've completely missed the poi=
nt.</div><div><br></div><div>We're all inventing a vocabulary here. It&=
#39;s not productive. We need to stop doing that.</div><div><br></div><div>=
Somebody needs to go study a real compiler and generate a vocabulary which =
that real compiler itself uses internally.=C2=A0 Otherwise we are wasting e=
ffort.</div></div></blockquote><div><br></div><div>Niall, can you elaborate=
on this point, and in particular how</div><div><a href=3D"https://github.c=
om/Quuxplusone/clang/commit/f755170d59c7b70d9f8358a79cc05a5eeb74f92f">https=
://github.com/Quuxplusone/clang/commit/f755170d59c7b70d9f8358a79cc05a5eeb74=
f92f</a><br></div><div><a href=3D"https://reviews.llvm.org/D50119">https://=
reviews.llvm.org/D50119</a><br></div><div>would not count as steps in that =
direction? =C2=A0(See also=C2=A0<a href=3D"https://reviews.llvm.org/D49317"=
>D49317</a>.)</div><div><br></div><div>Niall, if there's a specific ope=
ration that you'd like to know the name of, if you can describe it unam=
biguously, I volunteer to go find out what (if anything) Clang calls it.</d=
iv><div><br></div><div>What makes that tricky (AFAICT) is that mostly in th=
is thread we've been discussing operations that do not exist in the Sta=
ndard... so of course they don't exist in most compilers, either.</div>=
<div><br></div><div>=E2=80=93Arthur</div></div></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CADvuK0Jnh7FjVKiaFqXEVCVEN%2Bbo9opetg=
NDqnuDtonMqOV22A%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0Jnh7FjVK=
iaFqXEVCVEN%2Bbo9opetgNDqnuDtonMqOV22A%40mail.gmail.com</a>.<br />
--00000000000073f90005736909ca--
.
Author: florian.csdt@gmail.com
Date: Tue, 14 Aug 2018 12:28:32 -0700 (PDT)
Raw View
------=_Part_2040_1535640069.1534274912554
Content-Type: multipart/alternative;
boundary="----=_Part_2041_1625912820.1534274912555"
------=_Part_2041_1625912820.1534274912555
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 14 ao=C3=BBt 2018 19:57:49 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>
> On Tue, Aug 14, 2018 at 1:11 AM, <floria...@gmail.com <javascript:>>=20
> wrote:
>
>> Le mardi 14 ao=C3=BBt 2018 01:37:19 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>>>
>>> On Mon, Aug 13, 2018 at 3:11 PM, <floria...@gmail.com> wrote:
>>>
>>>> Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2, Arthur O'Dwyer a =C3=A9crit=
:
>>>>>
>>>>> On Mon, Aug 13, 2018 at 2:52 AM, <floria...@gmail.com> wrote:
>>>>>
>>>>>>
>>>>>> You seem to want all movable types to also be relocatable by saying:=
=20
>>>>>> if a type is not trivially relocatable, then relocate =3D memcpy + d=
estroy.
>>>>>> What I propose is that some types will not be relocatable at all=20
>>>>>> (more on this later). And the fallback is written by the user becaus=
e it=20
>>>>>> highly depends on where relocation is used.
>>>>>> For instance, there is no way to emulate=20
>>>>>> serialize+realloc+deserialize with your form of fallback.
>>>>>> As I don't provide any automatic fallback at the language level, the=
=20
>>>>>> user (might be a library writer) will need to write the fallback cod=
e=20
>>>>>> themselves (here: allocate+move+destroy+deallocate).
>>>>>>
>>>>>> So when you say "in my design, T is relocatable", I will now=20
>>>>>> understand: "T is movable and non relocatable; serialize+memcpy+dese=
rialize=20
>>>>>> could be emulated by move+destroy".
>>>>>> But I fail to see what you gain from this.
>>>>>>
>>>>>
>>>>> Our definitions are converging! This is good news. :)
>>>>>
>>>>> I am not too worried that you fail to see what we gain from P1144's=
=20
>>>>> definition of relocation (over yours), because vice versa I fail to s=
ee=20
>>>>> what we gain from your definition of relocation (over P1144's). I th=
ink=20
>>>>> that as we plug the holes in your definition, it is quickly convergin=
g to=20
>>>>> *almost* the same thing as P1144; therefore both definitions have=20
>>>>> just about the same advantages and disadvantages. The only thing I wo=
uld=20
>>>>> tout as a remaining major advantage of P1144 is that it has a proposa=
l with=20
>>>>> wording and a complete implementation on Godbolt =E2=80=94 and I will=
happily admit=20
>>>>> that this is purely circumstantial and does not necessarily indicate =
that=20
>>>>> yours *couldn't* have such an implementation (now that most of the=20
>>>>> holes are plugged).
>>>>>
>>>>
>>>> As I said quite a while ago, our two proposals are not mutually=20
>>>> exclusive. It is possible to modify slightly yours to let the possibil=
ity=20
>>>> to standardize mine.
>>>> The only modification really necessary would be:
>>>> template <class T> concept Relocatable =3D NothrowRelocatable<T>;
>>>> template <class T> concept NothrowRelocatable =3D TriviallyRelocatable=
<T
>>>> >;
>>>> instead of:
>>>> template <class T> concept Relocatable =3D MoveConstructible<T> &&=20
>>>> Destructible<T>;
>>>> template <class T> concept NothrowRelocatable =3D=20
>>>> NothrowMoveConstructible<T> && NothrowDestructible<T>;
>>>>
>>>
>>> I don't quite see what the former two lines are doing. You want things=
=20
>>> to be Relocatable iff they are TriviallyRelocatable? But what about thi=
ngs=20
>>> that are "relocatable but non-trivially so"? In P1144, that would be=
=20
>>> anything with a user-defined move-ctor and dtor; in your scheme, that w=
ould=20
>>> be anything with a user-defined `serialize` and `deserialize`.
>>>
>>> I think pursuing this line might confuse both of us even more, so I'd b=
e=20
>>> happy to drop it. :P
>>>
>>
>> Basically, the latter is what you have in your proposal currently.
>> And the former is what I propose for your proposal to be completely=20
>> forward compatible with mine.
>>
>> Because widening a contract is easy, but narrowing is almost impossible.
>>
>
> As I understand it, your scheme as proposed "for the near future" looks=
=20
> like this:
> - Any type with a trivial move-constructor and a trivial destructor is=20
> "trivially relocatable."
> - Any type with a non-trivial move-constructor and/or a non-trivial=20
> destructor is "not relocatable."
> - Any type with no move-constructor and/or no destructor is "not=20
> relocatable."
> - vector, swap, etc., can be optimized to use memcpy only for "trivially=
=20
> relocatable" types as described above, and fall back to move+destroy.
>
> yes
=20
> And for the "far future", it looks like this:
> - Any type with a trivial move-constructor and a trivial destructor will=
=20
> gain implicitly defaulted serialize/deserialize operators.
> - Any type with trivial serialize/deserialize operators is "trivially=20
> relocatable."
> - Any type with (non-trivial) serialize/deserialize operators is=20
> "relocatable."
> - Any type with no serialize/deserialize operators is "not relocatable."
> - vector, swap, etc., can be optimized to use memcpy only for=20
> "relocatable" types as described above, and fall back to move+destroy.
>
> mostly.
- Any type with a *default* move-constructor and a *default* destructor=20
will gain implicitly *defaulted* serialize/deserialize operators.
=20
> I'm sure I'm not describing the bullet points in exactly the same order o=
r=20
> with the same relative emphasis as you would... but is this a reasonably=
=20
> accurate summary of your "far future" proposal and the "completely forwar=
d=20
> compatible" ("near future") subset that you're talking about w.r.t. P1144=
?
>
>
Yes, that's what I envision.
I also want to highlight that modifying your proposal as I propose does not=
=20
reduce its usefulness. It only makes it more future proof.
=20
>
> Actually, a more argumentative-sounding set of bullet points for your "fa=
r=20
> future" proposal would be
> - Any type with a trivial move-constructor and a trivial destructor will=
=20
> gain implicitly defaulted serialize/deserialize operators.
> - Any type with trivial serialize/deserialize operators (even if it has n=
o=20
> move-constructor and/or no destructor) is "trivially relocatable."
> - Any type with (non-trivial) serialize/deserialize operators (even if it=
=20
> has no move-constructor and/or no destructor) is "relocatable."
> - Any type with no serialize/deserialize operators is "not relocatable."
> - vector, swap, etc., can be optimized to use memcpy only for=20
> "move-constructible, destructible, relocatable" types as described above,=
=20
> and fall back to move+destroy.
>
> Right? Because I think you wouldn't propose to change the constraints on=
=20
> vector, swap, etc., so move-constructibility and destructibility would=20
> still be required by their constraints?
>
>
I have no strong opinion on this subject. I would say that I see no reason=
=20
to keep the old constraint for relocatable types (because the implicitly=20
relocatable will be movable and destructible), but I'm fine with the=20
alternative.
=20
>
>
> [...]
>
>> Two messages ago, I understood you as wanting the following `One` to be=
=20
>>> trivially relocatable.
>>>
>>> struct One {
>>> std::vector<int, offset_ptr_allocator<int>> vec; // nontrivially=
=20
>>> relocatable, or perhaps nonrelocatable
>>> offset_ptr<int> ptr_into_vec; // nontrivially relocatable, or=20
>>> perhaps nonrelocatable
>>>
>>> // Warrant that "One" happens to be trivially relocatable for our=
=20
>>> purposes, even though its individual members are not trivially relocata=
ble
>>> operator serialize() =3D default;
>>> operator deserialize() =3D default;
>>> };
>>>
>>
>> You convinced me that an offset_ptr shouldn't be relocatable, so let be=
=20
>> it (which is the default anyway as offset_ptr move constructor is not=20
>> trivial).
>> One will then "inherits" the non-relocalibility from offset_ptr.
>>
>
> Okay, good. Agreed. And agreed that the user could provide a=20
> user-provided `operator serialize() {}` to get non-trivial-but-still-no-o=
p=20
> serialization if that's what they wanted.
>
> That's the idea. Here, to solve this minor issue, your attribute might=20
>> come handy.
>>
>
>
> Now here's our last major beef:
>
> [...]
>
>> Also, I have the impression that my proposal is a step forward to=20
>> standardize interprocess communication despite saying nothing about it.
>>
>> I am strongly of the opinion that your proposal does *nothing* in the=20
> direction of standardizing interprocess communication;=20
>
I agree that support for IPC has not changed with this proposal. What I=20
meant is: it a step in the good direction (I have the impression), but=20
we're still far from something usable.
in fact it is worse than nothing, because it claims the words "serialize"=
=20
> and "deserialize" for operations that fundamentally *cannot possibly work=
*=20
> unless the address space is shared. (E.g., your `std::list` example.)
>
That's true that this [de]serialize cannot work if the address is not=20
shared.
=20
> I do not know what "serialize" ought to mean, specifically, in the=20
> Standard, but I am confident that what human programmers mean by it is ve=
ry=20
> context-dependent. Your proposal works well for "serializing" something i=
n=20
> preparation for a memcpy (or memcpy-alike, such as realloc), but it does=
=20
> not and cannot work for "serializing" something in preparation for=20
> transmission over a network, or sharing into a different address space.=
=20
>
That's why I'm not fine with the [de]serialize names. I find it misleading.
=20
> Your proposal places "serialize" in the context of a type, such as=20
> std::list, but that is not good enough, because there are many different=
=20
> ways of serializing a std::list. Which way is correct depends on more=20
> context than just the type itself.
>
Agreed. The mechanism I propose is fine only for intraprocess communication=
..
I have the impression that to be able to standardize any form of IPC, we=20
would need to define in much more details what is the memory: especially=20
the concept of memory "region".
=20
> Could you fix this by adding a "context" parameter, like `operator=20
> serialize(std::serialization_kind =3D std::serialization_kind::in_process=
)`? =20
> Maybe. I wouldn't confidently say "no." But I wouldn't say "yes" either.=
=20
> I'd want to see some effort to actually work it out and use the scheme in=
=20
> practice and show that it works for someone's use-case somewhere in the=
=20
> world.
>
In term of interface, that's something we will be able to add afterwards.
In term of usefulness, I have to say I'm quite new to the IPC world. So=20
you're probably more knowledgeable than me on this subject.
=20
> The Folly/EASTL/P1144 definition of "relocatable" (which is also the=20
> BSL/Qt "moveable") has been shown to work for someone's use-case in=20
> practice. That's why I'm comfortable with the idea of standardizing both=
=20
> the technique and the vocabulary we use to describe it. As far as I am=
=20
> aware, nobody has ever tried this "serialize-in-place/memcpy/deserialize"=
=20
> idea in practice (which is a minor red flag), and I believe it is claimin=
g=20
> very valuable *new* real estate in a way that fundamentally *cannot=20
> possibly work* for future use-cases. =20
>
The thing is: one can be described in terms of the other. The other way=20
around is not possible. That's why I think that's a good idea to define it=
=20
like I did.
However, I'm not sure to understand your last point. Could you clarify it?
=20
>
> (That said, I have had a real hard time getting any engagement from the=
=20
> Folly or BSL people, and I have shamefully not yet reached out to EA. I'l=
l=20
> go write that email today. It is possible that they all ended up being=20
> unhappy with their concept of "relocatable," or found it was less importa=
nt=20
> in a move-semantics world than it had been in C++03.)
>
> =E2=80=93Arthur
>
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/ec2ec408-501f-4d30-8df3-9e97f0c9727b%40isocpp.or=
g.
------=_Part_2041_1625912820.1534274912555
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 14 ao=C3=BBt 2018 19:57:49 UTC+2, Arthur =
O'Dwyer a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr">On Tue, Aug 14, 2018 at 1:11 AM, <span dir=3D"ltr"><<=
a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"vy38URyJD=
gAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';retu=
rn true;" onclick=3D"this.href=3D'javascript:';return true;">floria=
....@gmail.com</a>></span> wrote:<br><div><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr">Le mardi 14 ao=C3=BBt 2018 01:37:19 UTC+2, Ar=
thur O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:=
solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"=
>On Mon, Aug 13, 2018 at 3:11 PM, <span dir=3D"ltr"><<a rel=3D"nofollow=
">floria...@gmail.com</a>></span> wrote:<div><div class=3D"gmail_quote">=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);p=
adding-left:1ex"><div dir=3D"ltr">Le lundi 13 ao=C3=BBt 2018 22:34:12 UTC+2=
, Arthur O'Dwyer a =C3=A9crit=C2=A0:<span><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-st=
yle:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"=
ltr">On Mon, Aug 13, 2018 at 2:52 AM, <span dir=3D"ltr"><<a rel=3D"nofo=
llow">floria...@gmail.com</a>></span> wrote:<br><div><div class=3D"gmail=
_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,20=
4,204);padding-left:1ex"><div dir=3D"ltr"><br>You seem to want all movable =
types to also be relocatable by saying: if a type is not trivially relocata=
ble, then relocate =3D memcpy + destroy.<br>What I propose is that some typ=
es will not be relocatable at all (more on this later). And the fallback is=
written by the user because it highly depends on where relocation is used.=
<br>For instance, there is no way to emulate serialize+realloc+deserialize =
with your form of fallback.<br>As I don't provide any automatic fallbac=
k at the language level, the user (might be a library writer) will need to =
write the fallback code themselves (here: allocate+move+destroy+<wbr>deallo=
cate).<br><br>So when you say "in my design, T is relocatable", I=
will now understand: "T is movable and non relocatable; serialize+mem=
cpy+deserialize could be emulated by move+destroy".<br>But I fail to s=
ee what you gain from this.<br></div></blockquote><div><br></div><div>Our d=
efinitions are converging!=C2=A0 This is good news. :)</div><div><br></div>=
<div>I am not too worried that you fail to see what we gain from P1144'=
s definition of relocation (over yours), because vice versa I fail to see w=
hat we gain from your definition of relocation (over P1144's).=C2=A0 I =
think that as we plug the holes in your definition, it is quickly convergin=
g to <i>almost</i> the same thing as P1144; therefore both definitions have=
just about the same advantages and disadvantages. The only thing I would t=
out as a remaining major advantage of P1144 is that it has a proposal with =
wording and a complete implementation on Godbolt =E2=80=94 and I will happi=
ly admit that this is purely circumstantial and does not necessarily indica=
te that yours <i>couldn't</i> have such an implementation (now that mos=
t of the holes are plugged).</div></div></div></div></blockquote><div><br><=
/div></span><div>As I said quite a while ago, our two proposals are not mut=
ually exclusive. It is possible to modify slightly yours to let the possibi=
lity to standardize mine.</div><div>The only modification really necessary =
would be:</div><div><div style=3D"background-color:rgb(250,250,250);border:=
1px solid rgb(187,187,187)"><code><div><span style=3D"color:rgb(0,0,136)">t=
emplate</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">class</span>=
<span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb(102,102,=
0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(102,0,102)">Relocatable</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">NothrowR=
elocatable</span><span style=3D"color:rgb(102,102,0)"><</span><span styl=
e=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">>;</=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0=
,0,136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span styl=
e=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">cl=
ass</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rg=
b(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(102,0,102)">NothrowRelocatable</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102=
,0,102)">TriviallyRelocatable</span><span style=3D"color:rgb(102,102,0)">&l=
t;</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(=
102,102,0)">>;</span><span style=3D"color:rgb(0,0,0)"><br></span></div><=
/code></div>instead of:</div><div><div style=3D"background-color:rgb(250,25=
0,250);border:1px solid rgb(187,187,187)"><code><div><span style=3D"color:r=
gb(0,0,136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span =
style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)=
">class</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"colo=
r:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,0,136)">concept</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,0,102)">Relocatable</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=3D</sp=
an><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,=
102)">MoveConstructible</span><span style=3D"color:rgb(102,102,0)"><</sp=
an><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,10=
2,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(102,102,0)">&&</span><span style=3D"color:rgb(0,0,0)"> </sp=
an><span style=3D"color:rgb(102,0,102)">Destructible</span><span style=3D"c=
olor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><s=
pan style=3D"color:rgb(102,102,0)">>;</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(0,0,136)">template</span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</=
span><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rg=
b(0,0,0)"> T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">concept=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(10=
2,0,102)">NothrowRelocatable</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(102,0,102)">NothrowMoveConstructible=
</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color=
:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">></span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">&am=
p;&</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,0,102)">NothrowDestructible</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"col=
or:rgb(102,102,0)">>;</span><span style=3D"color:rgb(0,0,0)"><br></span>=
</div></code></div></div></div></blockquote><div><br></div><div>I don't=
quite see what the former two lines are doing. You want things to be Reloc=
atable iff they are TriviallyRelocatable? But what about things that are &q=
uot;relocatable but non-trivially so"?=C2=A0 In P1144, that would be a=
nything with a user-defined move-ctor and dtor; in your scheme, that would =
be anything with a user-defined `serialize` and `deserialize`.</div><div><b=
r></div><div>I think pursuing this line might confuse both of us even more,=
so I'd be happy to drop it. :P</div></div></div></div></blockquote><di=
v><br></div></span><div>Basically, the latter is what you have in your prop=
osal currently.</div><div>And the former is what I propose for your proposa=
l to be completely forward compatible with mine.</div><div><br></div><div>B=
ecause widening a contract is easy, but narrowing is almost impossible.<br>=
</div></div></blockquote><div><br></div><div>As I understand it, your schem=
e as proposed "for the near future" looks like this:</div><div>- =
Any type with a trivial move-constructor and a trivial destructor is "=
trivially relocatable."</div><div>- Any type with a non-trivial move-c=
onstructor and/or a non-trivial destructor is "not relocatable."<=
/div><div><div>- Any type with no move-constructor and/or no destructor is =
"not relocatable."</div></div><div>- vector, swap, etc., can be o=
ptimized to use memcpy only for "trivially relocatable" types as =
described above, and fall back to move+destroy.</div><div><br></div></div><=
/div></div></blockquote><div>yes<br></div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quot=
e"><div></div><div>And for the "far future", it looks like this:<=
/div><div><div>- Any type with a trivial move-constructor and a trivial des=
tructor will gain implicitly defaulted serialize/deserialize operators.</di=
v><div>- Any type with trivial serialize/deserialize operators is "tri=
vially relocatable."<br></div><div>- Any type with (non-trivial) seria=
lize/deserialize operators is "relocatable."</div><div>- Any type=
with no serialize/deserialize operators is "not relocatable."</d=
iv><div>- vector, swap, etc., can be optimized to use memcpy only for "=
;relocatable" types as described above, and fall back to move+destroy.=
</div></div><div><br></div></div></div></div></blockquote><div>mostly.</div=
><div>- Any type with a <b>default</b> move-constructor and a <b>default</b=
> destructor will=20
gain implicitly <b>defaulted</b> serialize/deserialize operators.</div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div></div><div>I'm sure I'm not de=
scribing the bullet points in exactly the same order or with the same relat=
ive emphasis as you would... but is this a reasonably accurate summary of y=
our "far future" proposal and the "completely forward compat=
ible" ("near future") subset that you're talking about w=
..r.t. P1144?</div><div><br></div></div></div></div></blockquote><div><br></=
div><div>Yes, that's what I envision.</div><div>I also want to highligh=
t that modifying your proposal as I propose does not reduce its usefulness.=
It only makes it more future proof.<br></div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_=
quote"><div></div><div><br></div><div>Actually, a more argumentative-soundi=
ng set of bullet points for your "far future" proposal would be</=
div><div><div><div>- Any type with a trivial move-constructor and a trivial=
destructor will gain implicitly defaulted serialize/deserialize operators.=
</div><div>- Any type with trivial serialize/deserialize operators (even if=
it has no move-constructor and/or no destructor) is "trivially reloca=
table."</div><div>- Any type with (non-trivial) serialize/deserialize =
operators (even if it has no move-constructor and/or no destructor) is &quo=
t;relocatable."</div><div>- Any type with no serialize/deserialize ope=
rators is "not relocatable."</div><div>- vector, swap, etc., can =
be optimized to use memcpy only for "move-constructible, destructible,=
relocatable" types as described above, and fall back to move+destroy.=
</div></div></div><div><br></div><div>Right? Because I think you wouldn'=
;t propose to change the constraints on vector, swap, etc., so move-constru=
ctibility and destructibility would still be required by their constraints?=
</div><div><br></div></div></div></div></blockquote><div><br></div><div>I h=
ave no strong opinion on this subject. I would say that I see no reason to =
keep the old constraint for relocatable types (because the implicitly reloc=
atable will be movable and destructible), but I'm fine with the alterna=
tive.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><br></di=
v><div><br></div><div>[...]</div><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;bor=
der-left-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);pad=
ding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Two me=
ssages ago, I understood you as wanting the following `One` to be trivially=
relocatable.</div><div><br></div><div><div><div>struct One {</div><div>=C2=
=A0 =C2=A0 std::vector<int, offset_ptr_allocator<int>> vec; =C2=
=A0// nontrivially relocatable, or perhaps nonrelocatable</div><div>=C2=A0 =
=C2=A0 offset_ptr<int> ptr_into_vec; =C2=A0// nontrivially relocatabl=
e, or perhaps nonrelocatable</div><div><br></div><div>=C2=A0 =C2=A0 // Warr=
ant that "One" happens to be trivially relocatable for our purpos=
es, even though its individual members are not trivially relocatable</div><=
div>=C2=A0 =C2=A0 operator serialize() =3D default;</div><div>=C2=A0 =C2=A0=
operator deserialize() =3D default;</div><div>};</div></div></div></div></=
div></div></blockquote><div><br></div></span><div>You convinced me that an =
offset_ptr shouldn't be relocatable, so let be it (which is the default=
anyway as offset_ptr move constructor is not trivial).</div><div>One will =
then "inherits" the non-relocalibility from offset_ptr.<br></div>=
</div></blockquote><div><br></div><div>Okay, good. Agreed.=C2=A0 And agreed=
that the user could provide a user-provided `operator serialize() {}` to g=
et non-trivial-but-still-no-op serialization if that's what they wanted=
..</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-co=
lor:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>That's the=
idea. Here, to solve this minor issue, your attribute might come handy.<br=
></div><span><div></div></span></div></blockquote><div><br></div><div><br><=
/div><div>Now here's our last major beef:</div><div><br></div><div>[...=
]</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204=
,204);padding-left:1ex"><div dir=3D"ltr"><span><div>Also, I have the impres=
sion that my proposal is a step forward to standardize interprocess communi=
cation despite saying nothing about it.<br></div></span></div><span>
<p></p>
</span></blockquote><div>I am strongly of the opinion that your proposal do=
es <i>nothing</i> in the direction of standardizing interprocess communicat=
ion; </div></div></div></div></blockquote><div><br></div><div>I agree that =
support for IPC has not changed with this proposal. What I meant is: it a s=
tep in the good direction (I have the impression), but we're still far =
from something usable.<br></div><div><br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>in f=
act it is worse than nothing, because it claims the words "serialize&q=
uot; and "deserialize" for operations that fundamentally <i>canno=
t possibly work</i> unless the address space is shared. (E.g., your `std::l=
ist` example.)</div></div></div></div></blockquote><div><br></div><div>That=
's true that this [de]serialize cannot work if the address is not share=
d.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><div><div class=3D"gmail_quote"><div>I do not know what "s=
erialize" ought to mean, specifically, in the Standard, but I am confi=
dent that what human programmers mean by it is very context-dependent. Your=
proposal works well for "serializing" something in preparation f=
or a memcpy (or memcpy-alike, such as realloc), but it does not and cannot =
work for "serializing" something in preparation for transmission =
over a network, or sharing into a different address space. </div></div></di=
v></div></blockquote><div><br></div><div>That's why I'm not fine wi=
th the [de]serialize names. I find it misleading.<br></div><div>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cl=
ass=3D"gmail_quote"><div>Your proposal places "serialize" in the =
context of a type, such as std::list, but that is not good enough, because =
there are many different ways of serializing a std::list. Which way is corr=
ect depends on more context than just the type itself.</div></div></div></d=
iv></blockquote><div><br></div><div>Agreed. The mechanism I propose is fine=
only for intraprocess communication.</div><div><br></div><div>I have the i=
mpression that to be able to standardize any form of IPC, we would need to =
define in much more details what is the memory: especially the concept of m=
emory "region".<br></div><div>=C2=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div=
>Could you fix this by adding a "context" parameter, like `operat=
or serialize(std::serialization_<wbr>kind =3D std::serialization_kind::in_<=
wbr>process)`?=C2=A0 Maybe. I wouldn't confidently say "no." =
=C2=A0But I wouldn't say "yes" either. I'd want to see so=
me effort to actually work it out and use the scheme in practice and show t=
hat it works for someone's use-case somewhere in the world.</div></div>=
</div></div></blockquote><div><br></div><div>In term of interface, that'=
;s something we will be able to add afterwards.</div><div>In term of useful=
ness, I have to say I'm quite new to the IPC world. So you're proba=
bly more knowledgeable than me on this subject.<br></div><div>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><div>The Folly/EASTL/P1144 definition of "relocatabl=
e" (which is also the BSL/Qt "moveable") has been shown to w=
ork for someone's use-case in practice. That's why I'm comforta=
ble with the idea of standardizing both the technique and the vocabulary we=
use to describe it.=C2=A0 As far as I am aware, nobody has ever tried this=
"serialize-in-place/memcpy/<wbr>deserialize" idea in practice (w=
hich is a minor red flag), and I believe it is claiming very valuable <i>ne=
w</i> real estate in a way that fundamentally <i>cannot possibly work</i> f=
or future use-cases. =C2=A0</div></div></div></div></blockquote><div><br></=
div><div>The thing is: one can be described in terms of the other. The othe=
r way around is not possible. That's why I think that's a good idea=
to define it like I did.</div><div>However, I'm not sure to understand=
your last point. Could you clarify it?<br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div><br></div><div>(That said, I have had a real hard time getti=
ng any engagement from the Folly or BSL people, and I have shamefully not y=
et reached out to EA. I'll go write that email today. It is possible th=
at they all ended up being unhappy with their concept of "relocatable,=
" or found it was less important in a move-semantics world than it had=
been in C++03.)</div><div><br></div><div>=E2=80=93Arthur</div></div></div>=
</div>
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/ec2ec408-501f-4d30-8df3-9e97f0c9727b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ec2ec408-501f-4d30-8df3-9e97f0c9727b=
%40isocpp.org</a>.<br />
------=_Part_2041_1625912820.1534274912555--
------=_Part_2040_1535640069.1534274912554--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Tue, 14 Aug 2018 12:35:37 -0700 (PDT)
Raw View
------=_Part_2049_488111230.1534275337685
Content-Type: multipart/alternative;
boundary="----=_Part_2050_218014043.1534275337686"
------=_Part_2050_218014043.1534275337686
Content-Type: text/plain; charset="UTF-8"
>
>
>> You've completely missed the point.
>>
>> We're all inventing a vocabulary here. It's not productive. We need to
>> stop doing that.
>>
>> Somebody needs to go study a real compiler and generate a vocabulary
>> which that real compiler itself uses internally. Otherwise we are wasting
>> effort.
>>
>
> Niall, can you elaborate on this point, and in particular how
>
> https://github.com/Quuxplusone/clang/commit/f755170d59c7b70d9f8358a79cc05a5eeb74f92f
> https://reviews.llvm.org/D50119
> would not count as steps in that direction? (See also D49317
> <https://reviews.llvm.org/D49317>.)
>
I think those are doable for clang, where in many ways the source code *is* the
specification of the memory model.
I don't think they'll pass muster at WG21, because it works in terms of the
current standard.
>
> Niall, if there's a specific operation that you'd like to know the name
> of, if you can describe it unambiguously, I volunteer to go find out what
> (if anything) Clang calls it.
>
> What makes that tricky (AFAICT) is that mostly in this thread we've been
> discussing operations that do not exist in the Standard... so of course
> they don't exist in most compilers, either.
>
Spot on. Exactly the problem. Though, by rights compilers *should* have a
much better defined memory model than the standard. I don't know if clang's
is documented anywhere other than in source code. Well, I suppose LLVM has
a memory model of sorts. But I'd hope clang's is much more strictly defined.
If you go parse through *The CompCERT Memory Model Version 2*
(https://hal.inria.fr/hal-00703441/document), and compare it to the C++
standard's equivalent, some interesting things emerge. Under the CompCERT
memory model, relocation is idempotent, because objects are defined in
terms of having a unique identifier which isn't necessarily an address in
memory.
If you wished to add relocation however, it's trivially easy because the
rest of the memory model is so tightly defined. The real problem with the
C++ standard's memory model is the lack of it. You can't define relocation
with its current parlous state.
Now, what I was planning to do to propose adding support for memory maps
was to fuse parts of CompCERT's memory model into the C++ memory model (or
rather, from the much updated pre-v3 memory model
at http://cs.yale.edu/homes/wilke-pierre/itp-15.pdf). So basically perform
a major upgrade with a memory model actually capable of relocation, or
memory maps, and so on.
I fully expect that to go down like a lead balloon, but I think it's worth
doing anyway. If we can get C++ closer to formally verifiable, that's a
huge gain.
I appreciate that none of this is probably useful to your current efforts
Arthur. But all the constantly repeating discussion on this topic persuades
me it's become unavoidable if we want progress.
Niall
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3aa7ade2-7b6c-47b5-b6d3-c967c5270835%40isocpp.org.
------=_Part_2050_218014043.1534275337686
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div cla=
ss=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color=
:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span><div><br></div><=
/span><div>You've completely missed the point.</div><div><br></div><div=
>We're all inventing a vocabulary here. It's not productive. We nee=
d to stop doing that.</div><div><br></div><div>Somebody needs to go study a=
real compiler and generate a vocabulary which that real compiler itself us=
es internally.=C2=A0 Otherwise we are wasting effort.</div></div></blockquo=
te><div><br></div><div>Niall, can you elaborate on this point, and in parti=
cular how</div><div><a href=3D"https://github.com/Quuxplusone/clang/commit/=
f755170d59c7b70d9f8358a79cc05a5eeb74f92f" target=3D"_blank" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%=
2F%2Fgithub.com%2FQuuxplusone%2Fclang%2Fcommit%2Ff755170d59c7b70d9f8358a79c=
c05a5eeb74f92f\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGrUdMLGZCWKFw9H1Yf42=
cWgoL7-g';return true;" onclick=3D"this.href=3D'https://www.google.=
com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FQuuxplusone%2Fclang%2Fcommit%2Ff755=
170d59c7b70d9f8358a79cc05a5eeb74f92f\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQj=
CNGrUdMLGZCWKFw9H1Yf42cWgoL7-g';return true;">https://github.com/<wbr>Q=
uuxplusone/clang/commit/<wbr>f755170d59c7b70d9f8358a79cc05a<wbr>5eeb74f92f<=
/a><br></div><div><a href=3D"https://reviews.llvm.org/D50119" target=3D"_bl=
ank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.co=
m/url?q\x3dhttps%3A%2F%2Freviews.llvm.org%2FD50119\x26sa\x3dD\x26sntz\x3d1\=
x26usg\x3dAFQjCNFIjE4M66C31ZlXrWjXL5IBBgcjOA';return true;" onclick=3D"=
this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Freviews.llvm=
..org%2FD50119\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFIjE4M66C31ZlXrWjXL5I=
BBgcjOA';return true;">https://reviews.llvm.org/<wbr>D50119</a><br></di=
v><div>would not count as steps in that direction? =C2=A0(See also=C2=A0<a =
href=3D"https://reviews.llvm.org/D49317" target=3D"_blank" rel=3D"nofollow"=
onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2=
F%2Freviews.llvm.org%2FD49317\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGx5CA=
APgt9zSn8HRjTWEEn9QozpQ';return true;" onclick=3D"this.href=3D'http=
s://www.google.com/url?q\x3dhttps%3A%2F%2Freviews.llvm.org%2FD49317\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGx5CAAPgt9zSn8HRjTWEEn9QozpQ';return t=
rue;">D49317</a>.)</div></div></div></div></blockquote><div><br></div><div>=
I think those are doable for clang, where in many ways the source code <i>i=
s</i>=C2=A0the specification of the memory model.</div><div><br></div><div>=
I don't think they'll pass muster at WG21, because it works in term=
s of the current standard.</div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><b=
r></div><div>Niall, if there's a specific operation that you'd like=
to know the name of, if you can describe it unambiguously, I volunteer to =
go find out what (if anything) Clang calls it.</div><div><br></div><div>Wha=
t makes that tricky (AFAICT) is that mostly in this thread we've been d=
iscussing operations that do not exist in the Standard... so of course they=
don't exist in most compilers, either.</div></div></div></div></blockq=
uote><div><br></div><div>Spot on. Exactly the problem. Though, by rights co=
mpilers <i>should</i>=C2=A0have a much better defined memory model than the=
standard. I don't know if clang's is documented anywhere other tha=
n in source code. Well, I suppose LLVM has a memory model of sorts. But I&#=
39;d hope clang's is much more strictly defined.</div><div><br></div><d=
iv>If you go parse through <i>The CompCERT Memory Model Version 2</i> (http=
s://hal.inria.fr/hal-00703441/document), and compare it to the C++ standard=
's equivalent, some interesting things emerge. Under the CompCERT memor=
y model, relocation is idempotent, because objects are defined in terms of =
having a unique identifier which isn't necessarily an address in memory=
..</div><div><br></div><div>If you wished to add relocation however, it'=
s trivially easy because the rest of the memory model is so tightly defined=
.. The real problem with the C++ standard's memory model is the lack of =
it. You can't define relocation with its current parlous state.</div><d=
iv><br></div><div>Now, what I was planning to do to propose adding support =
for memory maps was to fuse parts of CompCERT's memory model into the C=
++ memory model (or rather, from the much updated pre-v3 memory model at=C2=
=A0http://cs.yale.edu/homes/wilke-pierre/itp-15.pdf). So basically perform =
a major upgrade with a memory model actually capable of relocation, or memo=
ry maps, and so on.</div><div><br></div><div>I fully expect that to go down=
like a lead balloon, but I think it's worth doing anyway. If we can ge=
t C++ closer to formally verifiable, that's a huge gain.</div><div><br>=
</div><div>I appreciate that none of this is probably useful to your curren=
t efforts Arthur. But all the constantly repeating discussion on this topic=
persuades me it's become unavoidable if we want progress.</div><div><b=
r></div><div>Niall</div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/3aa7ade2-7b6c-47b5-b6d3-c967c5270835%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3aa7ade2-7b6c-47b5-b6d3-c967c5270835=
%40isocpp.org</a>.<br />
------=_Part_2050_218014043.1534275337686--
------=_Part_2049_488111230.1534275337685--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 14 Aug 2018 16:55:20 -0400
Raw View
On 2018-08-14 15:28, florian.csdt@gmail.com wrote:
> Le mardi 14 ao=C3=BBt 2018 19:57:49 UTC+2, Arthur O'Dwyer a =C3=A9crit :
>> I do not know what "serialize" ought to mean, specifically, in the=20
>> Standard, but I am confident that what human programmers mean by it is v=
ery=20
>> context-dependent. Your proposal works well for "serializing" something =
in=20
>> preparation for a memcpy (or memcpy-alike, such as realloc), but it does=
=20
>> not and cannot work for "serializing" something in preparation for=20
>> transmission over a network, or sharing into a different address space.=
=20
>=20
> That's why I'm not fine with the [de]serialize names. I find it misleadin=
g.
"Dislocate" and "reseat"? "Denature" and "renew"?
Some of the D1031R1 suggestions might be applicable here, also.
English is, in some ways, an unfortunate language. "Relocate" *ought* to
be the opposite of "delocate", but it isn't. (Hence some of the original
confusion.)
(On a related note, how is it that "std::unbless" is the opposite of
"std::bless"? *Clearly* it should be "std::curse" ;-).)
--=20
Matthew
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/cbfecd61-9052-5321-0cf0-4a5d30effb4b%40gmail.com=
..
.
Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sun, 7 Oct 2018 22:35:03 +0200
Raw View
On Tue, Aug 14, 2018 at 12:28:32PM -0700, florian.csdt@gmail.com wrote:
>
> >> Also, I have the impression that my proposal is a step forward to
> >> standardize interprocess communication despite saying nothing about it.
> >>
> >> I am strongly of the opinion that your proposal does *nothing* in the
> > direction of standardizing interprocess communication;
> >
>
> I agree that support for IPC has not changed with this proposal. What I
> meant is: it a step in the good direction (I have the impression), but
> we're still far from something usable.
If we are to talk about IPC, don't we also need to talk about concurrently
running processes operating on the same memory and wouldn't that put a stake
through any pointer fiddling serializing functions?
This thread is about serializing objects to storage, not about any IPC with
more than two parties (the sender and the receiver) involved, and in that
case it still is a post the message and don't touch it kind of operation -
not one where both sides concurrently can access the object.
Now, such serialization might be valuable but do not call it IPC.
/MF
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20181007203503.GA12180%40noemi.bahnhof.se.
.