Topic: We need const_shared_ptr<T>
Author: Alexey Mamontov <caracrist@gmail.com>
Date: Wed, 24 Aug 2016 00:39:33 -0700 (PDT)
Raw View
------=_Part_131_73895828.1472024373197
Content-Type: multipart/alternative;
boundary="----=_Part_132_595332407.1472024373197"
------=_Part_132_595332407.1472024373197
Content-Type: text/plain; charset=UTF-8
There is an interesting concept of pointers pair: const_shared with
mutable_unique.
Const shared is move-constructible from mutable_unique: this enqures that
the value we have a const shared pointer to can not be references for edit
from any other location (the problem that shared_ptr<const T> can't solve).
mutable_unique is also move constructible from the const shared, while the
following logic is perfomed: if the source is the last reference, then the
same pointer is moved to the mutable instance, otherwise it creates a copy
using copy-constructor. This allowes to modify local instances while paying
the lowest possible price, and making copies only if there are some other
users of the same instance exist.
Returning a message body as const_share_ptr<vector<uint8>> might be a good
example, if there are further modifications of the body allowed. The actual
copying would be reduced to minimum.
Modiying local instance would look like the following:
const_shared_ptr<T> Modify(const_shared_ptr<T> val)
{
mutable_unique_ptr<T> tmp = move(val);
tmp->MakeChanges();
return move(tmp);
}
In case of the only instance moved to the function it would provide the
best perfomance while moving the same instance around.
It would be best to integrate with std::unique_ptr but since it takes only
the deleter in traits it is impossible to support it while we have to make
allocations for copy-constructed instances. In our code we have to define a
new type to pair the const_shared_ptr. The following are our public
interfaces:
template<typename T> class mutable_unique_ptr;
template<typename T> class const_shared_ptr;
template<typename T>
class mutable_unique_ptr
{
typedef T value_type;
typedef const_shared_ptr<value_type> const_shared_ptr_type;
mutable_unique_ptr(std::nullptr_t = nullptr);
mutable_unique_ptr(this_type && src);
explicit mutable_unique_ptr(value_type * pvalue);
mutable_unique_ptr(const_shared_ptr_type && src);
~mutable_unique_ptr();
this_type & operator=(std::nullptr_t other);
this_type & operator=(this_type && other);
this_type & operator=(const_shared_ptr_type && other);
void swap(this_type & other);
void reset(value_type * pvalue);
operator bool() const;
value_type * operator->() const;
value_type & operator*() const;
value_type * get() const;
};
template<typename T>
class const_shared_ptr
{
typedef T mutable_value_type;
typedef const mutable_value_type value_type;
typedef mutable_unique_ptr<mutable_value_type> mutable_value_ptr_type;
const_shared_ptr(std::nullptr_t = nullptr);
const_shared_ptr(const this_type & src);
const_shared_ptr(this_type && src);
const_shared_ptr(mutable_value_ptr_type && src);
explicit const_shared_ptr(mutable_value_type * pvalue);
~const_shared_ptr();
this_type & operator=(std::nullptr_t other);
this_type & operator=(const this_type & other);
this_type & operator=(this_type && other);
this_type & operator=(mutable_value_ptr_type && other);
void swap(this_type & other);
void reset(mutable_value_type * pvalue);
operator bool() const;
value_type * operator->() const;
value_type & operator*() const;
value_type * get() const;
};
We did not add support for custom allocators, we don't need it. But if it
finds it's way to the std, it should be initiated with allocator trait.
Thanks!
--
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/c3616c21-a33a-44b7-9912-b8ce927b57e9%40isocpp.org.
------=_Part_132_595332407.1472024373197
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>There is an interesting concept of pointers pair: con=
st_shared=C2=A0with mutable_unique.</div><div>Const shared is move-construc=
tible from mutable_unique: this enqures that the value we have a const shar=
ed=C2=A0pointer to can not be references for edit from any other location (=
the problem=C2=A0that shared_ptr<const T> can't solve).</div><div=
>mutable_unique is also move constructible from the const shared, while the=
following logic is perfomed: if the source is the last reference, then the=
same pointer is moved to the mutable instance, otherwise it creates a copy=
using copy-constructor. This allowes to modify local instances while payin=
g the lowest possible price, and making copies only if there are some other=
users of the same instance exist.</div><div>Returning a message body as co=
nst_share_ptr<vector<uint8>> might be a good example, if there =
are further modifications of the body allowed. The actual copying would be =
reduced to minimum.</div><div>Modiying local instance would look like the f=
ollowing:</div><div><br></div><div>const_shared_ptr<T> Modify(const_s=
hared_ptr<T> val)</div><div>{</div><div>=C2=A0 mutable_unique_ptr<=
T> tmp =3D move(val);</div><div>=C2=A0 tmp->MakeChanges();</div><div>=
=C2=A0 return move(tmp);</div><div>}</div><div><br></div><div>In case of th=
e only instance moved to the function it would provide the best perfomance =
while moving the same instance around.</div><div><br></div><div>It would be=
best to integrate with std::unique_ptr but since it takes only the deleter=
in traits it is impossible to support it while we have to make allocations=
for copy-constructed instances. In our code we have to define a new type t=
o pair the const_shared_ptr. The following are our public interfaces:</div>=
<div><br></div><div>template<typename T> class mutable_unique_ptr;<br=
>template<typename T> class const_shared_ptr;</div><div><br>template&=
lt;typename T><br>class mutable_unique_ptr<br>{<br>=C2=A0typedef T value=
_type;<br>=C2=A0typedef const_shared_ptr<value_type> const_shared_ptr=
_type;<br>=C2=A0<br>=C2=A0mutable_unique_ptr(std::nullptr_t =3D nullptr);<b=
r>=C2=A0mutable_unique_ptr(this_type && src);<br>=C2=A0explicit mut=
able_unique_ptr(value_type * pvalue);<br>=C2=A0mutable_unique_ptr(const_sha=
red_ptr_type && src);<br>=C2=A0~mutable_unique_ptr();<br>=C2=A0<br>=
=C2=A0this_type & operator=3D(std::nullptr_t other);<br>=C2=A0this_type=
& operator=3D(this_type && other);<br>=C2=A0this_type & op=
erator=3D(const_shared_ptr_type && other);<br>=C2=A0void swap(this_=
type & other);<br>=C2=A0void reset(value_type * pvalue);<br>=C2=A0opera=
tor bool() const;<br>=C2=A0value_type * operator->() const;<br>=C2=A0val=
ue_type & operator*() const;<br>=C2=A0value_type * get() const;<br>};</=
div><div>template<typename T><br>class const_shared_ptr<br>{<br>=C2=
=A0typedef T mutable_value_type;<br>=C2=A0typedef const mutable_value_type =
value_type;<br>=C2=A0typedef mutable_unique_ptr<mutable_value_type> m=
utable_value_ptr_type;</div><div>=C2=A0const_shared_ptr(std::nullptr_t =3D =
nullptr);<br>=C2=A0const_shared_ptr(const this_type & src);<br>=C2=A0co=
nst_shared_ptr(this_type && src);<br>=C2=A0const_shared_ptr(mutable=
_value_ptr_type && src);<br>=C2=A0explicit const_shared_ptr(mutable=
_value_type * pvalue);<br>=C2=A0~const_shared_ptr();<br>=C2=A0<br>=C2=A0thi=
s_type & operator=3D(std::nullptr_t other);<br>=C2=A0this_type & op=
erator=3D(const this_type & other);<br>=C2=A0this_type & operator=
=3D(this_type && other);<br>=C2=A0this_type & operator=3D(mutab=
le_value_ptr_type && other);<br>=C2=A0void swap(this_type & oth=
er);<br>=C2=A0void reset(mutable_value_type * pvalue);<br>=C2=A0operator bo=
ol() const;<br>=C2=A0value_type * operator->() const;<br>=C2=A0value_typ=
e & operator*() const;<br>=C2=A0value_type * get() const;<br>};</div><d=
iv><br></div><div>We did not add support for custom allocators, we don'=
t need it. But if it finds it's way to the std, it should be initiated =
with allocator trait.</div><div>Thanks!</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/c3616c21-a33a-44b7-9912-b8ce927b57e9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c3616c21-a33a-44b7-9912-b8ce927b57e9=
%40isocpp.org</a>.<br />
------=_Part_132_595332407.1472024373197--
------=_Part_131_73895828.1472024373197--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 24 Aug 2016 07:45:12 -0700 (PDT)
Raw View
------=_Part_1896_1075797409.1472049912504
Content-Type: multipart/alternative;
boundary="----=_Part_1897_848363053.1472049912504"
------=_Part_1897_848363053.1472049912504
Content-Type: text/plain; charset=UTF-8
On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov wrote:
>
> There is an interesting concept of pointers pair: const_shared with
> mutable_unique.
>
Const shared is move-constructible from mutable_unique: this enqures that
> the value we have a const shared pointer to can not be references for edit
> from any other location (the problem that shared_ptr<const T> can't solve).
>
Why does it not solve this problem? Outside of `const_pointer_cast` or
similar gymnastics, if you have a `shared_ptr<const T>`, you cannot convert
it into a `shared_ptr<T>`. Oh sure, you can always `get` the pointer and
`const_cast` it. But your `const_shared_ptr` has no way to prevent that
either.
So `shared_ptr<const T>` seems just as unchangeable as your proposed
`const_shared_ptr<T>`.
> mutable_unique is also move constructible from the const shared, while the
> following logic is perfomed: if the source is the last reference, then the
> same pointer is moved to the mutable instance, otherwise it creates a copy
> using copy-constructor. This allowes to modify local instances while paying
> the lowest possible price, and making copies only if there are some other
> users of the same instance exist.
>
I'm not sure I understand the conceptual foundation of what you're asking
for. I understand what all the pieces do; I just don't understand the
problem you're solving. In particular, why would constructing a
`mutable_unique` from a `const_shared_ptr` invoke copy construction? If
you're copying the value, then you're not accessing it by reference. So is
it a value type or a reference type?
Or is this some form of copy-on-write value semantics, generalized to all
types? If that's the idea behind this, then the names of these types are
completely wrong. They're not smart pointers; they're values. And the fact
that the const value is being "shared" is an implementation detail.
Indeed, I would even go so far as to say that, if this is the idea, then
giving it an existing object to govern is really the wrong interface. Such
a type should *create* the objects it manages internally; this would allow
the implementation to be more efficient (ala `make_shared`). That is, you
construct the mutable unique value type, then move the value into your
"const" COW shared object.
So what you really have is `unique_value<T>` and `shared_value<const T>`,
with conversions between them. This also permits you to have a mutable
`shared_value<T>` if a user wants it, rather than enforcing immutability at
the interface level.
Of course, that also raises the question of a `weak_ptr` equivalent. Does
this type need such a thing? With COW strings, the question was moot;
strings are dumb arrays, so there was never any question of whether a COW
string could have a circular reference to itself. But with generalized COW
objects, that possibility now exists.
--
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/444132ec-e8f3-400d-81b2-330a016702ee%40isocpp.org.
------=_Part_1897_848363053.1472049912504
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey =
Mamontov 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=
"><div>There is an interesting concept of pointers pair: const_shared=C2=A0=
with mutable_unique.=C2=A0</div></div></blockquote><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>Const shared is move-constructib=
le from mutable_unique: this enqures that the value we have a const shared=
=C2=A0pointer to can not be references for edit from any other location (th=
e problem=C2=A0that shared_ptr<const T> can't solve).</div></div>=
</blockquote><div><br>Why does it not solve this problem? Outside of `const=
_pointer_cast` or similar gymnastics, if you have a `shared_ptr<const T&=
gt;`, you cannot convert it into a `shared_ptr<T>`. Oh sure, you can =
always `get` the pointer and `const_cast` it. But your `const_shared_ptr` h=
as no way to prevent that either.<br><br>So `shared_ptr<const T>` see=
ms just as unchangeable as your proposed `const_shared_ptr<T>`.<br>=
=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>mutable_unique is also move constructible from the const shared, while =
the following logic is perfomed: if the source is the last reference, then =
the same pointer is moved to the mutable instance, otherwise it creates a c=
opy using copy-constructor. This allowes to modify local instances while pa=
ying the lowest possible price, and making copies only if there are some ot=
her users of the same instance exist.</div></div></blockquote><div><br>I=
9;m not sure I understand the conceptual foundation of what you're aski=
ng for. I understand what all the pieces do; I just don't understand th=
e problem you're solving. In particular, why would constructing a `muta=
ble_unique` from a `const_shared_ptr` invoke copy construction? If you'=
re copying the value, then you're not accessing it by reference. So is =
it a value type or a reference type?<br><br>Or is this some form of copy-on=
-write value semantics, generalized to all types? If that's the idea be=
hind this, then the names of these types are completely wrong. They're =
not smart pointers; they're values. And the fact that the const value i=
s being "shared" is an implementation detail.<br><br>Indeed, I wo=
uld even go so far as to say that, if this is the idea, then giving it an e=
xisting object to govern is really the wrong interface. Such a type should =
<i>create</i> the objects it manages internally; this would allow the imple=
mentation to be more efficient (ala `make_shared`). That is, you construct =
the mutable unique value type, then move the value into your "const&qu=
ot; COW shared object.<br><br>So what you really have is `unique_value<T=
>` and `shared_value<const T>`, with conversions between them. Thi=
s also permits you to have a mutable `shared_value<T>` if a user want=
s it, rather than enforcing immutability at the interface level.<br><br>Of =
course, that also raises the question of a `weak_ptr` equivalent. Does this=
type need such a thing? With COW strings, the question was moot; strings a=
re dumb arrays, so there was never any question of whether a COW string cou=
ld have a circular reference to itself. But with generalized COW objects, t=
hat possibility now exists.<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/444132ec-e8f3-400d-81b2-330a016702ee%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/444132ec-e8f3-400d-81b2-330a016702ee=
%40isocpp.org</a>.<br />
------=_Part_1897_848363053.1472049912504--
------=_Part_1896_1075797409.1472049912504--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 24 Aug 2016 16:57:32 -0700 (PDT)
Raw View
------=_Part_113_1998037309.1472083053026
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
> On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov wrote:
>=20
> There is an interesting concept of pointers pair: const_shared=C2=A0with =
mutable_unique.=C2=A0
>=20
> Const shared is move-constructible from mutable_unique: this enqures that=
the value we have a const shared=C2=A0pointer to can not be references for=
edit from any other location (the problem=C2=A0that shared_ptr<const T> ca=
n't solve).
>=20
> Why does it not solve this problem? Outside of `const_pointer_cast` or si=
milar gymnastics, if you have a `shared_ptr<const T>`, you cannot convert i=
t into a `shared_ptr<T>`. Oh sure, you can always `get` the pointer and `co=
nst_cast` it. But your `const_shared_ptr` has no way to prevent that either=
..
But there can be an already existing shared_ptr<T> aliasing your shared_ptr=
<T const>. The proposal here is that const_shared_ptr<T> can only be aliase=
d by other const_shared_ptr<T>s.
> > mutable_unique is also move constructible from the const shared, while =
the following logic is perfomed: if the source is the last reference, then =
the same pointer is moved to the mutable instance, otherwise it creates a c=
opy using copy-constructor. This allowes to modify local instances while pa=
ying the lowest possible price, and making copies only if there are some ot=
her users of the same instance exist.
>=20
> I'm not sure I understand the conceptual foundation of what you're asking=
for. I understand what all the pieces do; I just don't understand the prob=
lem you're solving. In particular, why would constructing a `mutable_unique=
` from a `const_shared_ptr` invoke copy construction? If you're copying the=
value, then you're not accessing it by reference. So is it a value type or=
a reference type?
In order to ensure that a const pointer cannot have its pointee concurrentl=
y modified by a mutable pointer.=20
> Or is this some form of copy-on-write value semantics, generalized to all=
types? If that's the idea behind this, then the names of these types are c=
ompletely wrong. They're not smart pointers; they're values. And the fact t=
hat the const value is being "shared" is an implementation detail.
Well, other than the clone operation being an observable side effect.=20
> Indeed, I would even go so far as to say that, if this is the idea, then =
giving it an existing object to govern is really the wrong interface. Such =
a type should create the objects it manages internally; this would allow th=
e implementation to be more efficient (ala `make_shared`). That is, you con=
struct the mutable unique value type, then move the value into your "const"=
COW shared object.
>=20
> So what you really have is `unique_value<T>` and `shared_value<const T>`,=
with conversions between them. This also permits you to have a mutable `sh=
ared_value<T>` if a user wants it, rather than enforcing immutability at th=
e interface level.
Would that allow enforcement of non modification by an aliasing value? Ther=
e's two sides to immutability; there's "I can't modify it" and there's "no-=
one can modify it".
> Of course, that also raises the question of a `weak_ptr` equivalent. Does=
this type need such a thing? With COW strings, the question was moot; stri=
ngs are dumb arrays, so there was never any question of whether a COW strin=
g could have a circular reference to itself. But with generalized COW objec=
ts, that possibility now exists.
Would such a weak_value<T const> be invalidated if all the shared_value<T c=
onst>s are converted to mutable?
--=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/45b8bdc7-5463-428a-aaef-d25ba0d2aa76%40isocpp.or=
g.
------=_Part_113_1998037309.1472083053026--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 24 Aug 2016 17:54:51 -0700 (PDT)
Raw View
------=_Part_103_961162589.1472086491661
Content-Type: multipart/alternative;
boundary="----=_Part_104_1344369097.1472086491661"
------=_Part_104_1344369097.1472086491661
Content-Type: text/plain; charset=UTF-8
On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote:
>
> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov
> wrote:
> >
> > There is an interesting concept of pointers pair: const_shared with
> mutable_unique.
> >
> > Const shared is move-constructible from mutable_unique: this enqures
> that the value we have a const shared pointer to can not be references for
> edit from any other location (the problem that shared_ptr<const T> can't
> solve).
> >
> > Why does it not solve this problem? Outside of `const_pointer_cast` or
> similar gymnastics, if you have a `shared_ptr<const T>`, you cannot convert
> it into a `shared_ptr<T>`. Oh sure, you can always `get` the pointer and
> `const_cast` it. But your `const_shared_ptr` has no way to prevent that
> either.
>
> But there can be an already existing shared_ptr<T> aliasing your
> shared_ptr<T const>.
Without a `const_cast` or similar? If you do `make_shared<const T>(...)`, I
have no idea how you would get the aliasing to `shared_ptr<T>` without a
`const_cast` or similar.
At least, not unless it's a pointer to a *different* `T`.
> The proposal here is that const_shared_ptr<T> can only be aliased by other
> const_shared_ptr<T>s.
>
> > > mutable_unique is also move constructible from the const shared, while
> the following logic is perfomed: if the source is the last reference, then
> the same pointer is moved to the mutable instance, otherwise it creates a
> copy using copy-constructor. This allowes to modify local instances while
> paying the lowest possible price, and making copies only if there are some
> other users of the same instance exist.
> >
> > I'm not sure I understand the conceptual foundation of what you're
> asking for. I understand what all the pieces do; I just don't understand
> the problem you're solving. In particular, why would constructing a
> `mutable_unique` from a `const_shared_ptr` invoke copy construction? If
> you're copying the value, then you're not accessing it by reference. So is
> it a value type or a reference type?
>
> In order to ensure that a const pointer cannot have its pointee
> concurrently modified by a mutable pointer.
>
Except that it can. The OP made it clear that if you take the last
`const_shared_ptr` and turn it into a `mutable_unique`, then the
`mutable_unique` *doesn't* copy the value; it merely takes ownership of the
pointer from the `const_shared_ptr`. So yes, it is possible to modify the
supposedly const object.
Just not directly through `const_shared_ptr`.
Structurally, this all seems very much like a generalized COW, with the
optimization that the last reference to the shared object doesn't need to
copy when it tries to write to it.
> > Or is this some form of copy-on-write value semantics, generalized to
> all types? If that's the idea behind this, then the names of these types
> are completely wrong. They're not smart pointers; they're values. And the
> fact that the const value is being "shared" is an implementation detail.
>
> Well, other than the clone operation being an observable side effect.
>
> > Indeed, I would even go so far as to say that, if this is the idea, then
> giving it an existing object to govern is really the wrong interface. Such
> a type should create the objects it manages internally; this would allow
> the implementation to be more efficient (ala `make_shared`). That is, you
> construct the mutable unique value type, then move the value into your
> "const" COW shared object.
> >
> > So what you really have is `unique_value<T>` and `shared_value<const
> T>`, with conversions between them. This also permits you to have a mutable
> `shared_value<T>` if a user wants it, rather than enforcing immutability at
> the interface level.
>
> Would that allow enforcement of non modification by an aliasing value?
> There's two sides to immutability; there's "I can't modify it" and there's
> "no-one can modify it".
>
Conceptually, it's a value type, so it wouldn't have aliasing of any form.
What would that even mean? Would you be aliasing a value with another
value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
interface, since it doesn't make sense.
After all, if your `const_shared_ptr<T>` actually owns some object of type
`U`, what would it mean to make a `mutable_unique` copy? Are you asking to
make a copy of the aliased pointer or the owned object? The latter is a bit
problematic, since it has been type-erased by that point.
> Of course, that also raises the question of a `weak_ptr` equivalent. Does
> this type need such a thing? With COW strings, the question was moot;
> strings are dumb arrays, so there was never any question of whether a COW
> string could have a circular reference to itself. But with generalized COW
> objects, that possibility now exists.
>
> Would such a weak_value<T const> be invalidated if all the shared_value<T
> const>s are converted to mutable?
They would have to be, since there are no shared values out there for it to
reference.
--
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/b627ed17-df02-4577-8a43-cc1af308673b%40isocpp.org.
------=_Part_104_1344369097.1472086491661
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward =
Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Wednesday, 24 =
August 2016 15:45:12 UTC+1, Nicol Bolas =C2=A0wrote:
<br>> On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov=
wrote:
<br>>=20
<br>> There is an interesting concept of pointers pair: const_shared=C2=
=A0with mutable_unique.=C2=A0
<br>>=20
<br>> Const shared is move-constructible from mutable_unique: this enqur=
es that the value we have a const shared=C2=A0pointer to can not be referen=
ces for edit from any other location (the problem=C2=A0that shared_ptr<c=
onst T> can't solve).
<br>>=20
<br>> Why does it not solve this problem? Outside of `const_pointer_cast=
` or similar gymnastics, if you have a `shared_ptr<const T>`, you can=
not convert it into a `shared_ptr<T>`. Oh sure, you can always `get` =
the pointer and `const_cast` it. But your `const_shared_ptr` has no way to =
prevent that either.
<br>
<br>But there can be an already existing shared_ptr<T> aliasing your =
shared_ptr<T const>.</blockquote><div><br>Without a `const_cast` or s=
imilar? If you do `make_shared<const T>(...)`, I have no idea how you=
would get the aliasing to `shared_ptr<T>` without a `const_cast` or =
similar.<br><br>At least, not unless it's a pointer to a <i>different</=
i> `T`.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">The pro=
posal here is that const_shared_ptr<T> can only be aliased by other c=
onst_shared_ptr<T>s.<br>
<br>> > mutable_unique is also move constructible from the const shar=
ed, while the following logic is perfomed: if the source is the last refere=
nce, then the same pointer is moved to the mutable instance, otherwise it c=
reates a copy using copy-constructor. This allowes to modify local instance=
s while paying the lowest possible price, and making copies only if there a=
re some other users of the same instance exist.
<br>>=20
<br>> I'm not sure I understand the conceptual foundation of what yo=
u're asking for. I understand what all the pieces do; I just don't =
understand the problem you're solving. In particular, why would constru=
cting a `mutable_unique` from a `const_shared_ptr` invoke copy construction=
? If you're copying the value, then you're not accessing it by refe=
rence. So is it a value type or a reference type?
<br>
<br>In order to ensure that a const pointer cannot have its pointee concurr=
ently modified by a mutable pointer.<br></blockquote><div><br>Except that i=
t can. The OP made it clear that if you take the last `const_shared_ptr` an=
d turn it into a `mutable_unique`, then the `mutable_unique` <i>doesn't=
</i> copy the value; it merely takes ownership of the pointer from the `con=
st_shared_ptr`. So yes, it is possible to modify the supposedly const objec=
t.<br><br>Just not directly through `const_shared_ptr`.<br><br>Structurally=
, this all seems very much like a generalized COW, with the optimization th=
at the last reference to the shared object doesn't need to copy when it=
tries to write to it.<br>=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;">
> Or is this some form of copy-on-write value semantics, generalized to =
all types? If that's the idea behind this, then the names of these type=
s are completely wrong. They're not smart pointers; they're values.=
And the fact that the const value is being "shared" is an implem=
entation detail.
<br>
<br>Well, other than the clone operation being an observable side effect.=
=20
<br>
<br>> Indeed, I would even go so far as to say that, if this is the idea=
, then giving it an existing object to govern is really the wrong interface=
.. Such a type should create the objects it manages internally; this would a=
llow the implementation to be more efficient (ala `make_shared`). That is, =
you construct the mutable unique value type, then move the value into your =
"const" COW shared object.
<br>>=20
<br>> So what you really have is `unique_value<T>` and `shared_val=
ue<const T>`, with conversions between them. This also permits you to=
have a mutable `shared_value<T>` if a user wants it, rather than enf=
orcing immutability at the interface level.
<br>
<br>Would that allow enforcement of non modification by an aliasing value? =
There's two sides to immutability; there's "I can't modify=
it" and there's "no-one can modify it".<br></blockquote=
><div><br>Conceptually, it's a value type, so it wouldn't have alia=
sing of any form. What would that even mean? Would you be aliasing a value =
with another value? Indeed, the OP excluded aliasing from `const_shared_ptr=
`'s interface, since it doesn't make sense.<br><br>After all, if yo=
ur `const_shared_ptr<T>` actually owns some object of type `U`, what =
would it mean to make a `mutable_unique` copy? Are you asking to make a cop=
y of the aliased pointer or the owned object? The latter is a bit problemat=
ic, since it has been type-erased by that point.<br><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">
> Of course, that also raises the question of a `weak_ptr` equivalent. D=
oes this type need such a thing? With COW strings, the question was moot; s=
trings are dumb arrays, so there was never any question of whether a COW st=
ring could have a circular reference to itself. But with generalized COW ob=
jects, that possibility now exists.
<br>
<br>Would such a weak_value<T const> be invalidated if all the shared=
_value<T const>s are converted to mutable?</blockquote><div><br>They =
would have to be, since there are no shared values out there for it to refe=
rence.<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/b627ed17-df02-4577-8a43-cc1af308673b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b627ed17-df02-4577-8a43-cc1af308673b=
%40isocpp.org</a>.<br />
------=_Part_104_1344369097.1472086491661--
------=_Part_103_961162589.1472086491661--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 25 Aug 2016 08:29:26 +0100
Raw View
--94eb2c0c9bb28fa001053ae05b88
Content-Type: text/plain; charset=UTF-8
On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <jmckesson@gmail.com> wrote:
>
> On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote:
>>
>> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
>> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov
wrote:
>> >
>> > There is an interesting concept of pointers pair: const_shared with
mutable_unique.
>> >
>> > Const shared is move-constructible from mutable_unique: this enqures
that the value we have a const shared pointer to can not be references for
edit from any other location (the problem that shared_ptr<const T> can't
solve).
>> >
>> > Why does it not solve this problem? Outside of `const_pointer_cast` or
similar gymnastics, if you have a `shared_ptr<const T>`, you cannot convert
it into a `shared_ptr<T>`. Oh sure, you can always `get` the pointer and
`const_cast` it. But your `const_shared_ptr` has no way to prevent that
either.
>>
>> But there can be an already existing shared_ptr<T> aliasing your
shared_ptr<T const>.
>
>
> Without a `const_cast` or similar? If you do `make_shared<const T>(...)`,
I have no idea how you would get the aliasing to `shared_ptr<T>` without a
`const_cast` or similar.
>
> At least, not unless it's a pointer to a different `T`.
If you do make_shared<T>(...) then you can get a shared_ptr<T const> later
that has the same target as the original shared_ptr<T>.
>>
>> The proposal here is that const_shared_ptr<T> can only be aliased by
other const_shared_ptr<T>s.
>>
>> > > mutable_unique is also move constructible from the const shared,
while the following logic is perfomed: if the source is the last reference,
then the same pointer is moved to the mutable instance, otherwise it
creates a copy using copy-constructor. This allowes to modify local
instances while paying the lowest possible price, and making copies only if
there are some other users of the same instance exist.
>> >
>> > I'm not sure I understand the conceptual foundation of what you're
asking for. I understand what all the pieces do; I just don't understand
the problem you're solving. In particular, why would constructing a
`mutable_unique` from a `const_shared_ptr` invoke copy construction? If
you're copying the value, then you're not accessing it by reference. So is
it a value type or a reference type?
>>
>> In order to ensure that a const pointer cannot have its pointee
concurrently modified by a mutable pointer.
>
>
> Except that it can. The OP made it clear that if you take the last
`const_shared_ptr` and turn it into a `mutable_unique`, then the
`mutable_unique` doesn't copy the value; it merely takes ownership of the
pointer from the `const_shared_ptr`. So yes, it is possible to modify the
supposedly const object.
>
> Just not directly through `const_shared_ptr`.
OK, but the point is that that modification is not observable to anyone who
has a const_shared_ptr.
> Structurally, this all seems very much like a generalized COW, with the
optimization that the last reference to the shared object doesn't need to
copy when it tries to write to it.
Yes. There's also some similarity to the reader-writer lock model.
>> > Indeed, I would even go so far as to say that, if this is the idea,
then giving it an existing object to govern is really the wrong interface.
Such a type should create the objects it manages internally; this would
allow the implementation to be more efficient (ala `make_shared`). That is,
you construct the mutable unique value type, then move the value into your
"const" COW shared object.
>> >
>> > So what you really have is `unique_value<T>` and `shared_value<const
T>`, with conversions between them. This also permits you to have a mutable
`shared_value<T>` if a user wants it, rather than enforcing immutability at
the interface level.
>>
>> Would that allow enforcement of non modification by an aliasing value?
There's two sides to immutability; there's "I can't modify it" and there's
"no-one can modify it".
>
>
> Conceptually, it's a value type, so it wouldn't have aliasing of any
form. What would that even mean? Would you be aliasing a value with another
value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
interface, since it doesn't make sense.
Sorry, I didn't mean aliasing in the sense of creating a shared_ptr to a
subobject, rather in the general sense of one pointer having the same
target as another pointer, or one reference having the same referent as
another reference.
In your shared_value scheme, a modification to one shared_value<T> can be
observed by another shared_value with the same target. Can you prevent a
shared_value<T const> having the same target as a shared_value<T>?
--
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/CAJnLdOZtv5pNcS5iUH0kAiCyfqHPWq%2BUF4ZKziPY5j4Doa_B5w%40mail.gmail.com.
--94eb2c0c9bb28fa001053ae05b88
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<p dir=3D"ltr"></p>
<p dir=3D"ltr">On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <<a hre=
f=3D"mailto:jmckesson@gmail.com">jmckesson@gmail.com</a>> wrote:<br>
><br>
> On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote=
:<br>
>><br>
>> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas =C2=A0wro=
te: <br>
>> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mam=
ontov wrote: <br>
>> > <br>
>> > There is an interesting concept of pointers pair: const_share=
d=C2=A0with mutable_unique.=C2=A0 <br>
>> > <br>
>> > Const shared is move-constructible from mutable_unique: this =
enqures that the value we have a const shared=C2=A0pointer to can not be re=
ferences for edit from any other location (the problem=C2=A0that shared_ptr=
<const T> can't solve). <br>
>> > <br>
>> > Why does it not solve this problem? Outside of `const_pointer=
_cast` or similar gymnastics, if you have a `shared_ptr<const T>`, yo=
u cannot convert it into a `shared_ptr<T>`. Oh sure, you can always `=
get` the pointer and `const_cast` it. But your `const_shared_ptr` has no wa=
y to prevent that either. <br>
>><br>
>> But there can be an already existing shared_ptr<T> aliasing =
your shared_ptr<T const>.<br>
><br>
><br>
> Without a `const_cast` or similar? If you do `make_shared<const T&g=
t;(...)`, I have no idea how you would get the aliasing to `shared_ptr<T=
>` without a `const_cast` or similar.<br>
><br>
> At least, not unless it's a pointer to a different `T`.</p>
<p dir=3D"ltr">If you do make_shared<T>(...) then you can get a share=
d_ptr<T const> later that has the same target as the original shared_=
ptr<T>.</p>
<p dir=3D"ltr">>><br>
>> The proposal here is that const_shared_ptr<T> can only be al=
iased by other const_shared_ptr<T>s.<br>
>><br>
>> > > mutable_unique is also move constructible from the const=
shared, while the following logic is perfomed: if the source is the last r=
eference, then the same pointer is moved to the mutable instance, otherwise=
it creates a copy using copy-constructor. This allowes to modify local ins=
tances while paying the lowest possible price, and making copies only if th=
ere are some other users of the same instance exist. <br>
>> > <br>
>> > I'm not sure I understand the conceptual foundation of wh=
at you're asking for. I understand what all the pieces do; I just don&#=
39;t understand the problem you're solving. In particular, why would co=
nstructing a `mutable_unique` from a `const_shared_ptr` invoke copy constru=
ction? If you're copying the value, then you're not accessing it by=
reference. So is it a value type or a reference type? <br>
>><br>
>> In order to ensure that a const pointer cannot have its pointee co=
ncurrently modified by a mutable pointer.<br>
><br>
><br>
> Except that it can. The OP made it clear that if you take the last `co=
nst_shared_ptr` and turn it into a `mutable_unique`, then the `mutable_uniq=
ue` doesn't copy the value; it merely takes ownership of the pointer fr=
om the `const_shared_ptr`. So yes, it is possible to modify the supposedly =
const object.<br>
><br>
> Just not directly through `const_shared_ptr`.</p>
<p dir=3D"ltr">OK, but the point is that that modification is not observabl=
e to anyone who has a const_shared_ptr.</p>
<p dir=3D"ltr">> Structurally, this all seems very much like a generaliz=
ed COW, with the optimization that the last reference to the shared object =
doesn't need to copy when it tries to write to it.</p>
<p dir=3D"ltr">Yes. There's also some similarity to the reader-writer l=
ock model. </p>
<p dir=3D"ltr">>> > Indeed, I would even go so far as to say that,=
if this is the idea, then giving it an existing object to govern is really=
the wrong interface. Such a type should create the objects it manages inte=
rnally; this would allow the implementation to be more efficient (ala `make=
_shared`). That is, you construct the mutable unique value type, then move =
the value into your "const" COW shared object. <br>
>> > <br>
>> > So what you really have is `unique_value<T>` and `share=
d_value<const T>`, with conversions between them. This also permits y=
ou to have a mutable `shared_value<T>` if a user wants it, rather tha=
n enforcing immutability at the interface level. <br>
>><br>
>> Would that allow enforcement of non modification by an aliasing va=
lue? There's two sides to immutability; there's "I can't m=
odify it" and there's "no-one can modify it".<br>
><br>
><br>
> Conceptually, it's a value type, so it wouldn't have aliasing =
of any form. What would that even mean? Would you be aliasing a value with =
another value? Indeed, the OP excluded aliasing from `const_shared_ptr`'=
;s interface, since it doesn't make sense.</p>
<p dir=3D"ltr">Sorry, I didn't mean aliasing in the sense of creating a=
shared_ptr to a subobject, rather in the general sense of one pointer havi=
ng the same target as another pointer, or one reference having the same ref=
erent as another reference. </p>
<p dir=3D"ltr">In your shared_value scheme, a modification to one shared_va=
lue<T> can be observed by another shared_value with the same target. =
Can you prevent a shared_value<T const> having the same target as a s=
hared_value<T>?<br>
</p>
<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/CAJnLdOZtv5pNcS5iUH0kAiCyfqHPWq%2BUF4=
ZKziPY5j4Doa_B5w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOZtv5pNcS=
5iUH0kAiCyfqHPWq%2BUF4ZKziPY5j4Doa_B5w%40mail.gmail.com</a>.<br />
--94eb2c0c9bb28fa001053ae05b88--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 25 Aug 2016 07:10:55 -0700 (PDT)
Raw View
------=_Part_382_1221259006.1472134255427
Content-Type: multipart/alternative;
boundary="----=_Part_383_2112385255.1472134255427"
------=_Part_383_2112385255.1472134255427
Content-Type: text/plain; charset=UTF-8
On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward Catmur wrote:
>
> On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <jmck...@gmail.com <javascript:>>
> wrote:
> >
> > On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote:
> >>
> >> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
> >> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov
> wrote:
> >> >
> >> > There is an interesting concept of pointers pair: const_shared with
> mutable_unique.
> >> >
> >> > Const shared is move-constructible from mutable_unique: this enqures
> that the value we have a const shared pointer to can not be references for
> edit from any other location (the problem that shared_ptr<const T> can't
> solve).
> >> >
> >> > Why does it not solve this problem? Outside of `const_pointer_cast`
> or similar gymnastics, if you have a `shared_ptr<const T>`, you cannot
> convert it into a `shared_ptr<T>`. Oh sure, you can always `get` the
> pointer and `const_cast` it. But your `const_shared_ptr` has no way to
> prevent that either.
> >>
> >> But there can be an already existing shared_ptr<T> aliasing your
> shared_ptr<T const>.
> >
> >
> > Without a `const_cast` or similar? If you do `make_shared<const
> T>(...)`, I have no idea how you would get the aliasing to `shared_ptr<T>`
> without a `const_cast` or similar.
> >
> > At least, not unless it's a pointer to a different `T`.
>
> If you do make_shared<T>(...) then you can get a shared_ptr<T const> later
> that has the same target as the original shared_ptr<T>.
>
I fail to see your point.
My point is that `shared_ptr` gives a user all the tools that
`const_shared_ptr` gives the user for making a non-modifiable shared
pointer to T. Namely, `shared_ptr<const T>`. If you create it `const`
initially, then nobody can take that away without an explicit `const_cast`
or similar construct.
This, in regards to the const-ness of `T`, `shared_ptr` is just as
guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:
template<typename T>
using const_shared_ptr = std::shared_ptr<std::add_const_t<T>>;
template<typename T, template ...Args>
auto make_const_shared(Args &&...args) { return std::make_shared<std::
add_const_t<T>>(std::forward<Args>(args)...); }
And you get the same `const` protection as the proposed `const_shared_ptr`,
so long as that is how you create them initially.
>> > Indeed, I would even go so far as to say that, if this is the idea,
> then giving it an existing object to govern is really the wrong interface.
> Such a type should create the objects it manages internally; this would
> allow the implementation to be more efficient (ala `make_shared`). That is,
> you construct the mutable unique value type, then move the value into your
> "const" COW shared object.
> >> >
> >> > So what you really have is `unique_value<T>` and `shared_value<const
> T>`, with conversions between them. This also permits you to have a mutable
> `shared_value<T>` if a user wants it, rather than enforcing immutability at
> the interface level.
> >>
> >> Would that allow enforcement of non modification by an aliasing value?
> There's two sides to immutability; there's "I can't modify it" and there's
> "no-one can modify it".
> >
> >
> > Conceptually, it's a value type, so it wouldn't have aliasing of any
> form. What would that even mean? Would you be aliasing a value with another
> value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
> interface, since it doesn't make sense.
>
> Sorry, I didn't mean aliasing in the sense of creating a shared_ptr to a
> subobject, rather in the general sense of one pointer having the same
> target as another pointer, or one reference having the same referent as
> another reference.
>
> In your shared_value scheme, a modification to one shared_value<T> can be
> observed by another shared_value with the same target. Can you prevent a
> shared_value<T const> having the same target as a shared_value<T>?
>
The same way as I showed for `shared_ptr`: make it `const` when you create
the first one.
If you want pure COW semantics from the type I've suggested, then you make
a `shared_value<const T>` at the point of origin. At no time do you make a
`shared_value<T>`.
The thing is, I've always thought we should have a `value_ptr<T>` type.
That is, a type that *certainly* allocates memory for `T`, moves via moving
the pointer, but copies itself by copying the object by value. This would
be useful for cases where `T` is expensive to move and/or throws on moving.
A `shared_value_ptr<T>` would not be an unreasonable pairing for such a
type. And then we could have `shared_value_ptr<const T>` serve the needs
the OP requires for COW gymnastics, so long as there is a conversion from
`shared_value_ptr` to `value_ptr` which is permitted to avoid a copy if the
`shared_value_ptr` moved into it is the last one.
--
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/5aacde88-8fb7-476c-a87e-df4d6ab001ae%40isocpp.org.
------=_Part_383_2112385255.1472134255427
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward C=
atmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><p dir=3D"ltr"></p=
>
<p dir=3D"ltr">On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <<a hre=
f=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"xkBJxMvzDQAJ" =
rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tr=
ue;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gma=
il.com</a>> wrote:<br>
><br>
> On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote=
:<br>
>><br>
>> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas =C2=A0wro=
te: <br>
>> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mam=
ontov wrote: <br>
>> > <br>
>> > There is an interesting concept of pointers pair: const_share=
d=C2=A0with mutable_unique.=C2=A0 <br>
>> > <br>
>> > Const shared is move-constructible from mutable_unique: this =
enqures that the value we have a const shared=C2=A0pointer to can not be re=
ferences for edit from any other location (the problem=C2=A0that shared_ptr=
<const T> can't solve). <br>
>> > <br>
>> > Why does it not solve this problem? Outside of `const_pointer=
_cast` or similar gymnastics, if you have a `shared_ptr<const T>`, yo=
u cannot convert it into a `shared_ptr<T>`. Oh sure, you can always `=
get` the pointer and `const_cast` it. But your `const_shared_ptr` has no wa=
y to prevent that either. <br>
>><br>
>> But there can be an already existing shared_ptr<T> aliasing =
your shared_ptr<T const>.<br>
><br>
><br>
> Without a `const_cast` or similar? If you do `make_shared<const T&g=
t;(...)`, I have no idea how you would get the aliasing to `shared_ptr<T=
>` without a `const_cast` or similar.<br>
><br>
> At least, not unless it's a pointer to a different `T`.</p>
<p dir=3D"ltr">If you do make_shared<T>(...) then you can get a share=
d_ptr<T const> later that has the same target as the original shared_=
ptr<T>.</p></blockquote><div><br>I fail to see your point.<br><br>My =
point is that `shared_ptr` gives a user all the tools that `const_shared_pt=
r` gives the user for making a non-modifiable shared pointer to T. Namely, =
`shared_ptr<const T>`. If you create it `const` initially, then nobod=
y can take that away without an explicit `const_cast` or similar construct.=
<br><br>This, in regards to the const-ness of `T`, `shared_ptr` is just as =
guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:<b=
r><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 2=
50); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1=
px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpr=
ettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">templa=
te</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">using</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> const_shared_ptr </span><span style=3D=
"color: #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">shared_ptr</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">add_const_t</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy"><</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><br></sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span s=
tyle=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: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=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: #606;" class=3D"styled-by-pr=
ettify">Args</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">auto</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> make_const_shar=
ed</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Args</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">args</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: #008;" class=3D"styled-by-pret=
tify">return</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">make_shared<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">add_const_t</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;" =
class=3D"styled-by-prettify">>>(</span><span style=3D"color: #000;" c=
lass=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">forward</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&g=
t;(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">args</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">)...);</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div=
><br>And you get the same `const` protection as the proposed `const_shared_=
ptr`, so long as that is how you create them initially.<br><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;"><p dir=3D"ltr">>> > Indeed,=
I would even go so far as to say that, if this is the idea, then giving it=
an existing object to govern is really the wrong interface. Such a type sh=
ould create the objects it manages internally; this would allow the impleme=
ntation to be more efficient (ala `make_shared`). That is, you construct th=
e mutable unique value type, then move the value into your "const"=
; COW shared object. <br>
>> > <br>
>> > So what you really have is `unique_value<T>` and `share=
d_value<const T>`, with conversions between them. This also permits y=
ou to have a mutable `shared_value<T>` if a user wants it, rather tha=
n enforcing immutability at the interface level. <br>
>><br>
>> Would that allow enforcement of non modification by an aliasing va=
lue? There's two sides to immutability; there's "I can't m=
odify it" and there's "no-one can modify it".<br>
><br>
><br>
> Conceptually, it's a value type, so it wouldn't have aliasing =
of any form. What would that even mean? Would you be aliasing a value with =
another value? Indeed, the OP excluded aliasing from `const_shared_ptr`'=
;s interface, since it doesn't make sense.</p>
<p dir=3D"ltr">Sorry, I didn't mean aliasing in the sense of creating a=
shared_ptr to a subobject, rather in the general sense of one pointer havi=
ng the same target as another pointer, or one reference having the same ref=
erent as another reference. </p>
<p dir=3D"ltr">In your shared_value scheme, a modification to one shared_va=
lue<T> can be observed by another shared_value with the same target. =
Can you prevent a shared_value<T const> having the same target as a s=
hared_value<T>?<br></p></blockquote><div><br>The same way as I showed=
for `shared_ptr`: make it `const` when you create the first one.<br><br>If=
you want pure COW semantics from the type I've suggested, then you mak=
e a `shared_value<const T>` at the point of origin. At no time do you=
make a `shared_value<T>`.<br><br>The thing is, I've always thoug=
ht we should have a `value_ptr<T>` type. That is, a type that *certai=
nly* allocates memory for `T`, moves via moving the pointer, but copies its=
elf by copying the object by value. This would be useful for cases where `T=
` is expensive to move and/or throws on moving.<br><br>A `shared_value_ptr&=
lt;T>` would not be an unreasonable pairing for such a type. And then we=
could have `shared_value_ptr<const T>` serve the needs the OP requir=
es for COW gymnastics, so long as there is a conversion from `shared_value_=
ptr` to `value_ptr` which is permitted to avoid a copy if the `shared_value=
_ptr` moved into it is the last one.<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/5aacde88-8fb7-476c-a87e-df4d6ab001ae%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5aacde88-8fb7-476c-a87e-df4d6ab001ae=
%40isocpp.org</a>.<br />
------=_Part_383_2112385255.1472134255427--
------=_Part_382_1221259006.1472134255427--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 25 Aug 2016 16:27:41 +0100
Raw View
--94eb2c08a748ea6743053ae7090f
Content-Type: text/plain; charset=UTF-8
On Thu, Aug 25, 2016 at 3:10 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward Catmur wrote:
>>
>> On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <jmck...@gmail.com> wrote:
>> >
>> > On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote:
>> >>
>> >> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
>> >> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov
>> wrote:
>> >> >
>> >> > There is an interesting concept of pointers pair: const_shared with
>> mutable_unique.
>> >> >
>> >> > Const shared is move-constructible from mutable_unique: this enqures
>> that the value we have a const shared pointer to can not be references for
>> edit from any other location (the problem that shared_ptr<const T> can't
>> solve).
>> >> >
>> >> > Why does it not solve this problem? Outside of `const_pointer_cast`
>> or similar gymnastics, if you have a `shared_ptr<const T>`, you cannot
>> convert it into a `shared_ptr<T>`. Oh sure, you can always `get` the
>> pointer and `const_cast` it. But your `const_shared_ptr` has no way to
>> prevent that either.
>> >>
>> >> But there can be an already existing shared_ptr<T> aliasing your
>> shared_ptr<T const>.
>> >
>> >
>> > Without a `const_cast` or similar? If you do `make_shared<const
>> T>(...)`, I have no idea how you would get the aliasing to `shared_ptr<T>`
>> without a `const_cast` or similar.
>> >
>> > At least, not unless it's a pointer to a different `T`.
>>
>> If you do make_shared<T>(...) then you can get a shared_ptr<T const>
>> later that has the same target as the original shared_ptr<T>.
>>
>
> I fail to see your point.
>
> My point is that `shared_ptr` gives a user all the tools that
> `const_shared_ptr` gives the user for making a non-modifiable shared
> pointer to T. Namely, `shared_ptr<const T>`. If you create it `const`
> initially, then nobody can take that away without an explicit `const_cast`
> or similar construct.
>
> This, in regards to the const-ness of `T`, `shared_ptr` is just as
> guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:
>
> template<typename T>
> using const_shared_ptr = std::shared_ptr<std::add_const_t<T>>;
>
> template<typename T, template ...Args>
> auto make_const_shared(Args &&...args) { return std::make_shared<std::add_
> const_t<T>>(std::forward<Args>(args)...); }
>
> And you get the same `const` protection as the proposed
> `const_shared_ptr`, so long as that is how you create them initially.
>
Right, but only if you control all the locations where the shared_ptr<T
[const]> is created and will be created in the future. If someone hands you
a shared_ptr<T const> it might have been created by make_shared<T const>
but it might also have been created initially as a make_shared<T>, so you
can't be sure that no-one has a mutable handle to the object you're
accessing.
> >> > Indeed, I would even go so far as to say that, if this is the idea,
>> then giving it an existing object to govern is really the wrong interface.
>> Such a type should create the objects it manages internally; this would
>> allow the implementation to be more efficient (ala `make_shared`). That is,
>> you construct the mutable unique value type, then move the value into your
>> "const" COW shared object.
>> >> >
>> >> > So what you really have is `unique_value<T>` and `shared_value<const
>> T>`, with conversions between them. This also permits you to have a mutable
>> `shared_value<T>` if a user wants it, rather than enforcing immutability at
>> the interface level.
>> >>
>> >> Would that allow enforcement of non modification by an aliasing value?
>> There's two sides to immutability; there's "I can't modify it" and there's
>> "no-one can modify it".
>> >
>> >
>> > Conceptually, it's a value type, so it wouldn't have aliasing of any
>> form. What would that even mean? Would you be aliasing a value with another
>> value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
>> interface, since it doesn't make sense.
>>
>> Sorry, I didn't mean aliasing in the sense of creating a shared_ptr to a
>> subobject, rather in the general sense of one pointer having the same
>> target as another pointer, or one reference having the same referent as
>> another reference.
>>
>> In your shared_value scheme, a modification to one shared_value<T> can be
>> observed by another shared_value with the same target. Can you prevent a
>> shared_value<T const> having the same target as a shared_value<T>?
>>
>
> The same way as I showed for `shared_ptr`: make it `const` when you create
> the first one.
>
> If you want pure COW semantics from the type I've suggested, then you make
> a `shared_value<const T>` at the point of origin. At no time do you make a
> `shared_value<T>`.
>
But then you can *never* modify it; you can only copy it to a new mutable
value. Which is great for functional purity, but could also be inefficient.
The thing is, I've always thought we should have a `value_ptr<T>` type.
> That is, a type that *certainly* allocates memory for `T`, moves via moving
> the pointer, but copies itself by copying the object by value. This would
> be useful for cases where `T` is expensive to move and/or throws on moving.
>
> A `shared_value_ptr<T>` would not be an unreasonable pairing for such a
> type. And then we could have `shared_value_ptr<const T>` serve the needs
> the OP requires for COW gymnastics, so long as there is a conversion from
> `shared_value_ptr` to `value_ptr` which is permitted to avoid a copy if the
> `shared_value_ptr` moved into it is the last one.
>
But that conversion would give you a value_ptr<T const>, so it would still
be immutable even when it should be safe to mutate.
--
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/CAJnLdObcZYq%2BNrDQHD4QN2V_qZV%2BqBzPcMeh3725g8eF6_JD6g%40mail.gmail.com.
--94eb2c08a748ea6743053ae7090f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Aug 25, 2016 at 3:10 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr">On Thursday, August 25, 20=
16 at 3:29:28 AM UTC-4, Edward Catmur wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><p dir=3D"ltr"=
></p>
<p dir=3D"ltr">On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <<a rel=
=3D"nofollow">jmck...@gmail.com</a>> wrote:<br>
><br>
> On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote=
:<br>
>><br>
>> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas =C2=A0wro=
te: <br>
>> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mam=
ontov wrote: <br>
>> > <br>
>> > There is an interesting concept of pointers pair: const_share=
d=C2=A0with mutable_unique.=C2=A0 <br>
>> > <br>
>> > Const shared is move-constructible from mutable_unique: this =
enqures that the value we have a const shared=C2=A0pointer to can not be re=
ferences for edit from any other location (the problem=C2=A0that shared_ptr=
<const T> can't solve). <br>
>> > <br>
>> > Why does it not solve this problem? Outside of `const_pointer=
_cast` or similar gymnastics, if you have a `shared_ptr<const T>`, yo=
u cannot convert it into a `shared_ptr<T>`. Oh sure, you can always `=
get` the pointer and `const_cast` it. But your `const_shared_ptr` has no wa=
y to prevent that either. <br>
>><br>
>> But there can be an already existing shared_ptr<T> aliasing =
your shared_ptr<T const>.<br>
><br>
><br>
> Without a `const_cast` or similar? If you do `make_shared<const T&g=
t;(...)`, I have no idea how you would get the aliasing to `shared_ptr<T=
>` without a `const_cast` or similar.<br>
><br>
> At least, not unless it's a pointer to a different `T`.</p>
<p dir=3D"ltr">If you do make_shared<T>(...) then you can get a share=
d_ptr<T const> later that has the same target as the original shared_=
ptr<T>.</p></blockquote><div><br>I fail to see your point.<br><br>My =
point is that `shared_ptr` gives a user all the tools that `const_shared_pt=
r` gives the user for making a non-modifiable shared pointer to T. Namely, =
`shared_ptr<const T>`. If you create it `const` initially, then nobod=
y can take that away without an explicit `const_cast` or similar construct.=
<br><br>This, in regards to the const-ness of `T`, `shared_ptr` is just as =
guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:<b=
r><br><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,=
136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><span =
style=3D"color:rgb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)=
"> T</span><span style=3D"color:rgb(102,102,0)">></span><span style=3D"c=
olor:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">using</span>=
<span style=3D"color:rgb(0,0,0)"> const_shared_ptr </span><span style=3D"co=
lor:rgb(102,102,0)">=3D</span><span style=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=
)">shared_ptr</span><span style=3D"color:rgb(102,102,0)"><</span><span s=
tyle=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)">add_<wbr>const_t</span><span style=
=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</sp=
an><span style=3D"color:rgb(102,102,0)">>>;</span><span style=3D"colo=
r:rgb(0,0,0)"><br><br></span><span style=3D"color:rgb(0,0,136)">template</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rg=
b(0,0,136)">typename</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)">template</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">...</span><span s=
tyle=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rgb(102,102,0=
)">></span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"co=
lor:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> make_const_s=
hared</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(102,0,102)">Args</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(102,102,0)">&&...</span><span style=3D"color:r=
gb(0,0,0)">args</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(102,102,0)">{</sp=
an><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,13=
6)">return</span><span style=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)">make_share=
d</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"colo=
r:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::</span><span=
style=3D"color:rgb(0,0,0)">add_<wbr>const_t</span><span style=3D"color:rgb=
(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span styl=
e=3D"color:rgb(102,102,0)">>>(</span><span style=3D"color:rgb(0,0,0)"=
>std</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"col=
or:rgb(0,0,0)">forward</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rgb(=
102,102,0)">><wbr>(</span><span style=3D"color:rgb(0,0,0)">args</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(102,102,0)">}</span></div></code></d=
iv><br>And you get the same `const` protection as the proposed `const_share=
d_ptr`, so long as that is how you create them initially.<br></div></div></=
blockquote><div><br></div><div>Right, but only if you control all the locat=
ions where the shared_ptr<T [const]> is created and will be created i=
n the future. If someone hands you a shared_ptr<T const> it might hav=
e been created by make_shared<T const> but it might also have been cr=
eated initially as a make_shared<T>, so you can't be sure that no=
-one has a mutable handle to the object you're accessing.</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><p dir=3D"ltr">>&g=
t; > Indeed, I would even go so far as to say that, if this is the idea,=
then giving it an existing object to govern is really the wrong interface.=
Such a type should create the objects it manages internally; this would al=
low the implementation to be more efficient (ala `make_shared`). That is, y=
ou construct the mutable unique value type, then move the value into your &=
quot;const" COW shared object. <br>
>> > <br>
>> > So what you really have is `unique_value<T>` and `share=
d_value<const T>`, with conversions between them. This also permits y=
ou to have a mutable `shared_value<T>` if a user wants it, rather tha=
n enforcing immutability at the interface level. <br>
>><br>
>> Would that allow enforcement of non modification by an aliasing va=
lue? There's two sides to immutability; there's "I can't m=
odify it" and there's "no-one can modify it".<br>
><br>
><br>
> Conceptually, it's a value type, so it wouldn't have aliasing =
of any form. What would that even mean? Would you be aliasing a value with =
another value? Indeed, the OP excluded aliasing from `const_shared_ptr`'=
;s interface, since it doesn't make sense.</p>
<p dir=3D"ltr">Sorry, I didn't mean aliasing in the sense of creating a=
shared_ptr to a subobject, rather in the general sense of one pointer havi=
ng the same target as another pointer, or one reference having the same ref=
erent as another reference. </p>
<p dir=3D"ltr">In your shared_value scheme, a modification to one shared_va=
lue<T> can be observed by another shared_value with the same target. =
Can you prevent a shared_value<T const> having the same target as a s=
hared_value<T>?<br></p></blockquote><div><br>The same way as I showed=
for `shared_ptr`: make it `const` when you create the first one.<br><br>If=
you want pure COW semantics from the type I've suggested, then you mak=
e a `shared_value<const T>` at the point of origin. At no time do you=
make a `shared_value<T>`.<br></div></div></blockquote><div><br></div=
><div>But then you can *never* modify it; you can only copy it to a new mut=
able value. Which is great for functional purity, but could also be ineffic=
ient.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204)=
;border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>The thing =
is, I've always thought we should have a `value_ptr<T>` type. Tha=
t is, a type that *certainly* allocates memory for `T`, moves via moving th=
e pointer, but copies itself by copying the object by value. This would be =
useful for cases where `T` is expensive to move and/or throws on moving.<br=
><br>A `shared_value_ptr<T>` would not be an unreasonable pairing for=
such a type. And then we could have `shared_value_ptr<const T>` serv=
e the needs the OP requires for COW gymnastics, so long as there is a conve=
rsion from `shared_value_ptr` to `value_ptr` which is permitted to avoid a =
copy if the `shared_value_ptr` moved into it is the last one.</div></div></=
blockquote><div><br></div><div>But that conversion would give you a value_p=
tr<T const>, so it would still be immutable even when it should be sa=
fe to mutate.<br></div><div><br></div><div>=C2=A0</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/CAJnLdObcZYq%2BNrDQHD4QN2V_qZV%2BqBzP=
cMeh3725g8eF6_JD6g%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObcZYq%=
2BNrDQHD4QN2V_qZV%2BqBzPcMeh3725g8eF6_JD6g%40mail.gmail.com</a>.<br />
--94eb2c08a748ea6743053ae7090f--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 25 Aug 2016 12:37:39 -0700 (PDT)
Raw View
------=_Part_757_83444341.1472153859711
Content-Type: multipart/alternative;
boundary="----=_Part_758_812604166.1472153859711"
------=_Part_758_812604166.1472153859711
Content-Type: text/plain; charset=UTF-8
On Thursday, August 25, 2016 at 11:27:43 AM UTC-4, Edward Catmur wrote:
>
> On Thu, Aug 25, 2016 at 3:10 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward Catmur wrote:
>>>
>>> On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <jmck...@gmail.com> wrote:
>>> >
>>> > On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote:
>>> >>
>>> >> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
>>> >> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mamontov
>>> wrote:
>>> >> >
>>> >> > There is an interesting concept of pointers pair: const_shared with
>>> mutable_unique.
>>> >> >
>>> >> > Const shared is move-constructible from mutable_unique: this
>>> enqures that the value we have a const shared pointer to can not be
>>> references for edit from any other location (the problem that
>>> shared_ptr<const T> can't solve).
>>> >> >
>>> >> > Why does it not solve this problem? Outside of `const_pointer_cast`
>>> or similar gymnastics, if you have a `shared_ptr<const T>`, you cannot
>>> convert it into a `shared_ptr<T>`. Oh sure, you can always `get` the
>>> pointer and `const_cast` it. But your `const_shared_ptr` has no way to
>>> prevent that either.
>>> >>
>>> >> But there can be an already existing shared_ptr<T> aliasing your
>>> shared_ptr<T const>.
>>> >
>>> >
>>> > Without a `const_cast` or similar? If you do `make_shared<const
>>> T>(...)`, I have no idea how you would get the aliasing to `shared_ptr<T>`
>>> without a `const_cast` or similar.
>>> >
>>> > At least, not unless it's a pointer to a different `T`.
>>>
>>> If you do make_shared<T>(...) then you can get a shared_ptr<T const>
>>> later that has the same target as the original shared_ptr<T>.
>>>
>>
>> I fail to see your point.
>>
>> My point is that `shared_ptr` gives a user all the tools that
>> `const_shared_ptr` gives the user for making a non-modifiable shared
>> pointer to T. Namely, `shared_ptr<const T>`. If you create it `const`
>> initially, then nobody can take that away without an explicit `const_cast`
>> or similar construct.
>>
>> This, in regards to the const-ness of `T`, `shared_ptr` is just as
>> guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:
>>
>> template<typename T>
>> using const_shared_ptr = std::shared_ptr<std::add_const_t<T>>;
>>
>> template<typename T, template ...Args>
>> auto make_const_shared(Args &&...args) { return std::make_shared<std::
>> add_const_t<T>>(std::forward<Args>(args)...); }
>>
>> And you get the same `const` protection as the proposed
>> `const_shared_ptr`, so long as that is how you create them initially.
>>
>
> Right, but only if you control all the locations where the shared_ptr<T
> [const]> is created and will be created in the future. If someone hands you
> a shared_ptr<T const> it might have been created by make_shared<T const>
> but it might also have been created initially as a make_shared<T>, so you
> can't be sure that no-one has a mutable handle to the object you're
> accessing.
>
If you don't control those locations, how can you possibly force them to
use `const_shared_ptr`?
Furthermore, the OP makes it clear that you *can* change the value of `T`
within a `const_shared_ptr`. In the OP's design, you can pass a non-const
T* to `const_shared_ptr`'s constructor. You can still use that non-`const`
pointer to modify the object's state. If the OP were interested in perfect
const-ness, then the API would only be accessible via an emplacement
constructor/make_const_shared_ptr, either of which would prevent someone
from having a non-const pointer without an explicit `const_cast`.
So if the goal of this design is to ensure `const`-ness of the object at
all times (outside of casts), then the given design is flawed.
>> > Indeed, I would even go so far as to say that, if this is the idea,
>>> then giving it an existing object to govern is really the wrong interface.
>>> Such a type should create the objects it manages internally; this would
>>> allow the implementation to be more efficient (ala `make_shared`). That is,
>>> you construct the mutable unique value type, then move the value into your
>>> "const" COW shared object.
>>> >> >
>>> >> > So what you really have is `unique_value<T>` and
>>> `shared_value<const T>`, with conversions between them. This also permits
>>> you to have a mutable `shared_value<T>` if a user wants it, rather than
>>> enforcing immutability at the interface level.
>>> >>
>>> >> Would that allow enforcement of non modification by an aliasing
>>> value? There's two sides to immutability; there's "I can't modify it" and
>>> there's "no-one can modify it".
>>> >
>>> >
>>> > Conceptually, it's a value type, so it wouldn't have aliasing of any
>>> form. What would that even mean? Would you be aliasing a value with another
>>> value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
>>> interface, since it doesn't make sense.
>>>
>>> Sorry, I didn't mean aliasing in the sense of creating a shared_ptr to a
>>> subobject, rather in the general sense of one pointer having the same
>>> target as another pointer, or one reference having the same referent as
>>> another reference.
>>>
>>> In your shared_value scheme, a modification to one shared_value<T> can
>>> be observed by another shared_value with the same target. Can you prevent a
>>> shared_value<T const> having the same target as a shared_value<T>?
>>>
>>
>> The same way as I showed for `shared_ptr`: make it `const` when you
>> create the first one.
>>
>> If you want pure COW semantics from the type I've suggested, then you
>> make a `shared_value<const T>` at the point of origin. At no time do you
>> make a `shared_value<T>`.
>>
>
> But then you can *never* modify it; you can only copy it to a new mutable
> value. Which is great for functional purity, but could also be inefficient.
>
That's what the OP asked for. You start with `const_shared_ptr` and hand it
out to people who can make mutable *copies* of it.
The thing is, I've always thought we should have a `value_ptr<T>` type.
>> That is, a type that *certainly* allocates memory for `T`, moves via moving
>> the pointer, but copies itself by copying the object by value. This would
>> be useful for cases where `T` is expensive to move and/or throws on moving.
>>
>> A `shared_value_ptr<T>` would not be an unreasonable pairing for such a
>> type. And then we could have `shared_value_ptr<const T>` serve the needs
>> the OP requires for COW gymnastics, so long as there is a conversion from
>> `shared_value_ptr` to `value_ptr` which is permitted to avoid a copy if the
>> `shared_value_ptr` moved into it is the last one.
>>
>
> But that conversion would give you a value_ptr<T const>, so it would still
> be immutable even when it should be safe to mutate.
>
This is perfectly legitimate code:
const T t = ...;
T t2 = std::move(t);
Why should this not be legitimate:
shared_value_ptr<const T> t = ...;
value_ptr<T> t2 = std::move(t);
The only difference between the two is that the last one can not copy the
object if `t` is the last owner of that memory.
--
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/0aaf31f0-d92b-467a-8517-353a82478c39%40isocpp.org.
------=_Part_758_812604166.1472153859711
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 25, 2016 at 11:27:43 AM UTC-4,=
Edward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Aug 25, 2016 at 3:10 PM, N=
icol Bolas <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"Sg9K2OQNDgAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">jmck...@gmail.com</a>></span> wrote:<br><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex"><div dir=3D"ltr">On Thursday, August 25, 2016 at 3:29:28 AM UT=
C-4, Edward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);=
border-left-style:solid;padding-left:1ex"><p dir=3D"ltr"></p>
<p dir=3D"ltr">On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <<a rel=
=3D"nofollow">jmck...@gmail.com</a>> wrote:<br>
><br>
> On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur wrote=
:<br>
>><br>
>> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas =C2=A0wro=
te: <br>
>> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey Mam=
ontov wrote: <br>
>> > <br>
>> > There is an interesting concept of pointers pair: const_share=
d=C2=A0with mutable_unique.=C2=A0 <br>
>> > <br>
>> > Const shared is move-constructible from mutable_unique: this =
enqures that the value we have a const shared=C2=A0pointer to can not be re=
ferences for edit from any other location (the problem=C2=A0that shared_ptr=
<const T> can't solve). <br>
>> > <br>
>> > Why does it not solve this problem? Outside of `const_pointer=
_cast` or similar gymnastics, if you have a `shared_ptr<const T>`, yo=
u cannot convert it into a `shared_ptr<T>`. Oh sure, you can always `=
get` the pointer and `const_cast` it. But your `const_shared_ptr` has no wa=
y to prevent that either. <br>
>><br>
>> But there can be an already existing shared_ptr<T> aliasing =
your shared_ptr<T const>.<br>
><br>
><br>
> Without a `const_cast` or similar? If you do `make_shared<const T&g=
t;(...)`, I have no idea how you would get the aliasing to `shared_ptr<T=
>` without a `const_cast` or similar.<br>
><br>
> At least, not unless it's a pointer to a different `T`.</p>
<p dir=3D"ltr">If you do make_shared<T>(...) then you can get a share=
d_ptr<T const> later that has the same target as the original shared_=
ptr<T>.</p></blockquote><div><br>I fail to see your point.<br><br>My =
point is that `shared_ptr` gives a user all the tools that `const_shared_pt=
r` gives the user for making a non-modifiable shared pointer to T. Namely, =
`shared_ptr<const T>`. If you create it `const` initially, then nobod=
y can take that away without an explicit `const_cast` or similar construct.=
<br><br>This, in regards to the const-ness of `T`, `shared_ptr` is just as =
guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:<b=
r><br><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,=
136)">template</span><span style=3D"color:rgb(102,102,0)"><</span><span =
style=3D"color:rgb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)=
"> T</span><span style=3D"color:rgb(102,102,0)">></span><span style=3D"c=
olor:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">using</span>=
<span style=3D"color:rgb(0,0,0)"> const_shared_ptr </span><span style=3D"co=
lor:rgb(102,102,0)">=3D</span><span style=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=
)">shared_ptr</span><span style=3D"color:rgb(102,102,0)"><</span><span s=
tyle=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)">add_<wbr>const_t</span><span style=
=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</sp=
an><span style=3D"color:rgb(102,102,0)">>>;</span><span style=3D"colo=
r:rgb(0,0,0)"><br><br></span><span style=3D"color:rgb(0,0,136)">template</s=
pan><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rg=
b(0,0,136)">typename</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)">template</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">...</span><span s=
tyle=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rgb(102,102,0=
)">></span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"co=
lor:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> make_const_s=
hared</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(102,0,102)">Args</span><span style=3D"color:rgb(0,0,0)"> </span><spa=
n style=3D"color:rgb(102,102,0)">&&...</span><span style=3D"color:r=
gb(0,0,0)">args</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(102,102,0)">{</sp=
an><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,13=
6)">return</span><span style=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)">make_share=
d</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"colo=
r:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::</span><span=
style=3D"color:rgb(0,0,0)">add_<wbr>const_t</span><span style=3D"color:rgb=
(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span styl=
e=3D"color:rgb(102,102,0)">>>(</span><span style=3D"color:rgb(0,0,0)"=
>std</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"col=
or:rgb(0,0,0)">forward</span><span style=3D"color:rgb(102,102,0)"><</spa=
n><span style=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rgb(=
102,102,0)">><wbr>(</span><span style=3D"color:rgb(0,0,0)">args</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(102,102,0)">}</span></div></code></d=
iv><br>And you get the same `const` protection as the proposed `const_share=
d_ptr`, so long as that is how you create them initially.<br></div></div></=
blockquote><div><br></div><div>Right, but only if you control all the locat=
ions where the shared_ptr<T [const]> is created and will be created i=
n the future. If someone hands you a shared_ptr<T const> it might hav=
e been created by make_shared<T const> but it might also have been cr=
eated initially as a make_shared<T>, so you can't be sure that no=
-one has a mutable handle to the object you're accessing.</div></div></=
div></div></blockquote><div><br>If you don't control those locations, h=
ow can you possibly force them to use `const_shared_ptr`?<br><br>Furthermor=
e, the OP makes it clear that you <i>can</i>
change the value of `T` within a `const_shared_ptr`. In the OP's=20
design, you can pass a non-const T* to `const_shared_ptr`'s constructor=
..
You can still use that non-`const` pointer to modify the object's=20
state. If the OP were interested in perfect const-ness, then the API=20
would only be accessible via an emplacement=20
constructor/make_const_shared_ptr, either of which would prevent someone
from having a non-const pointer without an explicit `const_cast`.<br><br>S=
o if the goal of this design is to ensure `const`-ness of the object at all=
times (outside of casts), then the given design is flawed.<br><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;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-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex"><div dir=3D"ltr"><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><p dir=3D"ltr">>> > Indeed, I would even go so far as to say t=
hat, if this is the idea, then giving it an existing object to govern is re=
ally the wrong interface. Such a type should create the objects it manages =
internally; this would allow the implementation to be more efficient (ala `=
make_shared`). That is, you construct the mutable unique value type, then m=
ove the value into your "const" COW shared object. <br>
>> > <br>
>> > So what you really have is `unique_value<T>` and `share=
d_value<const T>`, with conversions between them. This also permits y=
ou to have a mutable `shared_value<T>` if a user wants it, rather tha=
n enforcing immutability at the interface level. <br>
>><br>
>> Would that allow enforcement of non modification by an aliasing va=
lue? There's two sides to immutability; there's "I can't m=
odify it" and there's "no-one can modify it".<br>
><br>
><br>
> Conceptually, it's a value type, so it wouldn't have aliasing =
of any form. What would that even mean? Would you be aliasing a value with =
another value? Indeed, the OP excluded aliasing from `const_shared_ptr`'=
;s interface, since it doesn't make sense.</p>
<p dir=3D"ltr">Sorry, I didn't mean aliasing in the sense of creating a=
shared_ptr to a subobject, rather in the general sense of one pointer havi=
ng the same target as another pointer, or one reference having the same ref=
erent as another reference. </p>
<p dir=3D"ltr">In your shared_value scheme, a modification to one shared_va=
lue<T> can be observed by another shared_value with the same target. =
Can you prevent a shared_value<T const> having the same target as a s=
hared_value<T>?<br></p></blockquote><div><br>The same way as I showed=
for `shared_ptr`: make it `const` when you create the first one.<br><br>If=
you want pure COW semantics from the type I've suggested, then you mak=
e a `shared_value<const T>` at the point of origin. At no time do you=
make a `shared_value<T>`.<br></div></div></blockquote><div><br></div=
><div>But then you can *never* modify it; you can only copy it to a new mut=
able value. Which is great for functional purity, but could also be ineffic=
ient.</div></div></div></div></blockquote><div><br>That's what the OP a=
sked for. You start with `const_shared_ptr` and hand it out to people who c=
an make mutable <i>copies</i> of it.<br><br></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><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex"><div dir=3D"ltr"><div>The thing is, I've always t=
hought we should have a `value_ptr<T>` type. That is, a type that *ce=
rtainly* allocates memory for `T`, moves via moving the pointer, but copies=
itself by copying the object by value. This would be useful for cases wher=
e `T` is expensive to move and/or throws on moving.<br><br>A `shared_value_=
ptr<T>` would not be an unreasonable pairing for such a type. And the=
n we could have `shared_value_ptr<const T>` serve the needs the OP re=
quires for COW gymnastics, so long as there is a conversion from `shared_va=
lue_ptr` to `value_ptr` which is permitted to avoid a copy if the `shared_v=
alue_ptr` moved into it is the last one.</div></div></blockquote><div><br><=
/div><div>But that conversion would give you a value_ptr<T const>, so=
it would still be immutable even when it should be safe to mutate.<br></di=
v></div></div></div></blockquote><div><br>This is perfectly legitimate code=
:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250=
, 250); border-color: rgb(187, 187, 187); border-style: solid; border-width=
: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">con=
st</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T t </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: #660;" class=3D"styled-by-prettify">...;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>T t2 </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">move</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></=
div></code></div><br>Why should this not be legitimate:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #000;" class=3D"styled-by-prettify">shared_value_ptr</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> t </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: #660;" class=3D"styled-by=
-prettify">...;</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>value_ptr</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> t2 </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=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"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></div></code></div><br>The only difference between the =
two is that the last one can not copy the object if `t` is the last owner o=
f that memory.<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/0aaf31f0-d92b-467a-8517-353a82478c39%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0aaf31f0-d92b-467a-8517-353a82478c39=
%40isocpp.org</a>.<br />
------=_Part_758_812604166.1472153859711--
------=_Part_757_83444341.1472153859711--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Fri, 26 Aug 2016 00:05:34 +0100
Raw View
--001a1146ed6e768d7a053aed6fb8
Content-Type: text/plain; charset=UTF-8
On 25 Aug 2016 8:37 p.m., "Nicol Bolas" <jmckesson@gmail.com> wrote:
>
>
>
> On Thursday, August 25, 2016 at 11:27:43 AM UTC-4, Edward Catmur wrote:
>>
>> On Thu, Aug 25, 2016 at 3:10 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>> On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward Catmur wrote:
>>>>
>>>> On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <jmck...@gmail.com> wrote:
>>>> >
>>>> > On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Edward Catmur
wrote:
>>>> >>
>>>> >> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nicol Bolas wrote:
>>>> >> > On Wednesday, August 24, 2016 at 3:39:33 AM UTC-4, Alexey
Mamontov wrote:
>>>> >> >
>>>> >> > There is an interesting concept of pointers pair:
const_shared with mutable_unique.
>>>> >> >
>>>> >> > Const shared is move-constructible from mutable_unique: this
enqures that the value we have a const shared pointer to can not be
references for edit from any other location (the problem that
shared_ptr<const T> can't solve).
>>>> >> >
>>>> >> > Why does it not solve this problem? Outside of
`const_pointer_cast` or similar gymnastics, if you have a `shared_ptr<const
T>`, you cannot convert it into a `shared_ptr<T>`. Oh sure, you can always
`get` the pointer and `const_cast` it. But your `const_shared_ptr` has no
way to prevent that either.
>>>> >>
>>>> >> But there can be an already existing shared_ptr<T> aliasing your
shared_ptr<T const>.
>>>> >
>>>> >
>>>> > Without a `const_cast` or similar? If you do `make_shared<const
T>(...)`, I have no idea how you would get the aliasing to `shared_ptr<T>`
without a `const_cast` or similar.
>>>> >
>>>> > At least, not unless it's a pointer to a different `T`.
>>>>
>>>> If you do make_shared<T>(...) then you can get a shared_ptr<T const>
later that has the same target as the original shared_ptr<T>.
>>>
>>>
>>> I fail to see your point.
>>>
>>> My point is that `shared_ptr` gives a user all the tools that
`const_shared_ptr` gives the user for making a non-modifiable shared
pointer to T. Namely, `shared_ptr<const T>`. If you create it `const`
initially, then nobody can take that away without an explicit `const_cast`
or similar construct.
>>>
>>> This, in regards to the const-ness of `T`, `shared_ptr` is just as
guaranteed as the proposed `const_shared_ptr`. Indeed, you could do this:
>>>
>>> template<typename T>
>>> using const_shared_ptr = std::shared_ptr<std::add_const_t<T>>;
>>>
>>> template<typename T, template ...Args>
>>> auto make_const_shared(Args &&...args) { return
std::make_shared<std::add_const_t<T>>(std::forward<Args>(args)...); }
>>>
>>> And you get the same `const` protection as the proposed
`const_shared_ptr`, so long as that is how you create them initially.
>>
>>
>> Right, but only if you control all the locations where the shared_ptr<T
[const]> is created and will be created in the future. If someone hands you
a shared_ptr<T const> it might have been created by make_shared<T const>
but it might also have been created initially as a make_shared<T>, so you
can't be sure that no-one has a mutable handle to the object you're
accessing.
>
>
> If you don't control those locations, how can you possibly force them to
use `const_shared_ptr`?
Well, if they want to call your code they're going to have to create a
const_shared_ptr at some point.
> Furthermore, the OP makes it clear that you can change the value of `T`
within a `const_shared_ptr`. In the OP's design, you can pass a non-const
T* to `const_shared_ptr`'s constructor. You can still use that non-`const`
pointer to modify the object's state. If the OP were interested in perfect
const-ness, then the API would only be accessible via an emplacement
constructor/make_const_shared_ptr, either of which would prevent someone
from having a non-const pointer without an explicit `const_cast`.
>
> So if the goal of this design is to ensure `const`-ness of the object at
all times (outside of casts), then the given design is flawed.
Ah, I missed that bit, thanks. Still, an API that promotes correctness but
can be subverted is still better than an API that requires constant
vigilance to use safely.
>>>> >> > Indeed, I would even go so far as to say that, if this is the
idea, then giving it an existing object to govern is really the wrong
interface. Such a type should create the objects it manages internally;
this would allow the implementation to be more efficient (ala
`make_shared`). That is, you construct the mutable unique value type, then
move the value into your "const" COW shared object.
>>>> >> >
>>>> >> > So what you really have is `unique_value<T>` and
`shared_value<const T>`, with conversions between them. This also permits
you to have a mutable `shared_value<T>` if a user wants it, rather than
enforcing immutability at the interface level.
>>>> >>
>>>> >> Would that allow enforcement of non modification by an aliasing
value? There's two sides to immutability; there's "I can't modify it" and
there's "no-one can modify it".
>>>> >
>>>> >
>>>> > Conceptually, it's a value type, so it wouldn't have aliasing of any
form. What would that even mean? Would you be aliasing a value with another
value? Indeed, the OP excluded aliasing from `const_shared_ptr`'s
interface, since it doesn't make sense.
>>>>
>>>> Sorry, I didn't mean aliasing in the sense of creating a shared_ptr to
a subobject, rather in the general sense of one pointer having the same
target as another pointer, or one reference having the same referent as
another reference.
>>>>
>>>> In your shared_value scheme, a modification to one shared_value<T> can
be observed by another shared_value with the same target. Can you prevent a
shared_value<T const> having the same target as a shared_value<T>?
>>>
>>>
>>> The same way as I showed for `shared_ptr`: make it `const` when you
create the first one.
>>>
>>> If you want pure COW semantics from the type I've suggested, then you
make a `shared_value<const T>` at the point of origin. At no time do you
make a `shared_value<T>`.
>>
>>
>> But then you can *never* modify it; you can only copy it to a new
mutable value. Which is great for functional purity, but could also be
inefficient.
>
>
> That's what the OP asked for. You start with `const_shared_ptr` and hand
it out to people who can make mutable copies of it.
Yes, but OP also wants to be able to convert it back to mutable form if
that can be done safely.
>>> The thing is, I've always thought we should have a `value_ptr<T>` type.
That is, a type that *certainly* allocates memory for `T`, moves via moving
the pointer, but copies itself by copying the object by value. This would
be useful for cases where `T` is expensive to move and/or throws on moving.
>>>
>>> A `shared_value_ptr<T>` would not be an unreasonable pairing for such a
type. And then we could have `shared_value_ptr<const T>` serve the needs
the OP requires for COW gymnastics, so long as there is a conversion from
`shared_value_ptr` to `value_ptr` which is permitted to avoid a copy if the
`shared_value_ptr` moved into it is the last one.
>>
>>
>> But that conversion would give you a value_ptr<T const>, so it would
still be immutable even when it should be safe to mutate.
>
>
> This is perfectly legitimate code:
>
> const T t = ...;
> T t2 = std::move(t);
Legitimate, but it has unexpected semantics; it doesn't call the move
constructor.
> Why should this not be legitimate:
>
> shared_value_ptr<const T> t = ...;
> value_ptr<T> t2 = std::move(t);
>
> The only difference between the two is that the last one can not copy the
object if `t` is the last owner of that memory.
Well, it wouldn't work if the constructor of shared_value_ptr<T const> ends
up calling new T const, because the pointee would be an actually const
object.
The implementation would have to remove_const on T before constructing the
pointee, which would inhibit optimization if you didn't intend ever to use
it mutably.
--
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/CAJnLdOYm6mQ2BAA4Ys%3DOwBECTH6ugQcTU4Ns5wkxyqozGt%2BTkQ%40mail.gmail.com.
--001a1146ed6e768d7a053aed6fb8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<p dir=3D"ltr"></p>
<p dir=3D"ltr">On 25 Aug 2016 8:37 p.m., "Nicol Bolas" <<a hre=
f=3D"mailto:jmckesson@gmail.com">jmckesson@gmail.com</a>> wrote:<br>
><br>
><br>
><br>
> On Thursday, August 25, 2016 at 11:27:43 AM UTC-4, Edward Catmur wrote=
:<br>
>><br>
>> On Thu, Aug 25, 2016 at 3:10 PM, Nicol Bolas <<a href=3D"mailto=
:jmck...@gmail.com">jmck...@gmail.com</a>> wrote:<br>
>>><br>
>>> On Thursday, August 25, 2016 at 3:29:28 AM UTC-4, Edward Catmu=
r wrote:<br>
>>>><br>
>>>> On 25 Aug 2016 1:54 a.m., "Nicol Bolas" <<a h=
ref=3D"mailto:jmck...@gmail.com">jmck...@gmail.com</a>> wrote:<br>
>>>> ><br>
>>>> > On Wednesday, August 24, 2016 at 7:57:33 PM UTC-4, Ed=
ward Catmur wrote:<br>
>>>> >><br>
>>>> >> On Wednesday, 24 August 2016 15:45:12 UTC+1, Nico=
l Bolas =C2=A0wrote: <br>
>>>> >> > On Wednesday, August 24, 2016 at 3:39:33 AM =
UTC-4, Alexey Mamontov wrote: <br>
>>>> >> > <br>
>>>> >> > There is an interesting concept of pointers =
pair: const_shared=C2=A0with mutable_unique.=C2=A0 <br>
>>>> >> > <br>
>>>> >> > Const shared is move-constructible from muta=
ble_unique: this enqures that the value we have a const shared=C2=A0pointer=
to can not be references for edit from any other location (the problem=C2=
=A0that shared_ptr<const T> can't solve). <br>
>>>> >> > <br>
>>>> >> > Why does it not solve this problem? Outside =
of `const_pointer_cast` or similar gymnastics, if you have a `shared_ptr<=
;const T>`, you cannot convert it into a `shared_ptr<T>`. Oh sure,=
you can always `get` the pointer and `const_cast` it. But your `const_shar=
ed_ptr` has no way to prevent that either. <br>
>>>> >><br>
>>>> >> But there can be an already existing shared_ptr&l=
t;T> aliasing your shared_ptr<T const>.<br>
>>>> ><br>
>>>> ><br>
>>>> > Without a `const_cast` or similar? If you do `make_sh=
ared<const T>(...)`, I have no idea how you would get the aliasing to=
`shared_ptr<T>` without a `const_cast` or similar.<br>
>>>> ><br>
>>>> > At least, not unless it's a pointer to a differen=
t `T`.<br>
>>>><br>
>>>> If you do make_shared<T>(...) then you can get a sha=
red_ptr<T const> later that has the same target as the original share=
d_ptr<T>.<br>
>>><br>
>>><br>
>>> I fail to see your point.<br>
>>><br>
>>> My point is that `shared_ptr` gives a user all the tools that =
`const_shared_ptr` gives the user for making a non-modifiable shared pointe=
r to T. Namely, `shared_ptr<const T>`. If you create it `const` initi=
ally, then nobody can take that away without an explicit `const_cast` or si=
milar construct.<br>
>>><br>
>>> This, in regards to the const-ness of `T`, `shared_ptr` is jus=
t as guaranteed as the proposed `const_shared_ptr`. Indeed, you could do th=
is:<br>
>>><br>
>>> template<typename T><br>
>>> using const_shared_ptr =3D std::shared_ptr<std::add_const_t=
<T>>;<br>
>>><br>
>>> template<typename T, template ...Args><br>
>>> auto make_const_shared(Args &&...args) { return std::m=
ake_shared<std::add_const_t<T>>(std::forward<Args>(args).=
...); }<br>
>>><br>
>>> And you get the same `const` protection as the proposed `const=
_shared_ptr`, so long as that is how you create them initially.<br>
>><br>
>><br>
>> Right, but only if you control all the locations where the shared_=
ptr<T [const]> is created and will be created in the future. If someo=
ne hands you a shared_ptr<T const> it might have been created by make=
_shared<T const> but it might also have been created initially as a m=
ake_shared<T>, so you can't be sure that no-one has a mutable han=
dle to the object you're accessing.<br>
><br>
><br>
> If you don't control those locations, how can you possibly force t=
hem to use `const_shared_ptr`?</p>
<p dir=3D"ltr">Well, if they want to call your code they're going to ha=
ve to create a const_shared_ptr at some point. </p>
<p dir=3D"ltr">> Furthermore, the OP makes it clear that you can change =
the value of `T` within a `const_shared_ptr`. In the OP's design, you c=
an pass a non-const T* to `const_shared_ptr`'s constructor. You can sti=
ll use that non-`const` pointer to modify the object's state. If the OP=
were interested in perfect const-ness, then the API would only be accessib=
le via an emplacement constructor/make_const_shared_ptr, either of which wo=
uld prevent someone from having a non-const pointer without an explicit `co=
nst_cast`.<br>
><br>
> So if the goal of this design is to ensure `const`-ness of the object =
at all times (outside of casts), then the given design is flawed.</p>
<p dir=3D"ltr">Ah, I missed that bit, thanks. Still, an API that promotes c=
orrectness but can be subverted is still better than an API that requires c=
onstant vigilance to use safely. </p>
<p dir=3D"ltr">>>>> >> > Indeed, I would even go so fa=
r as to say that, if this is the idea, then giving it an existing object to=
govern is really the wrong interface. Such a type should create the object=
s it manages internally; this would allow the implementation to be more eff=
icient (ala `make_shared`). That is, you construct the mutable unique value=
type, then move the value into your "const" COW shared object. <=
br>
>>>> >> > <br>
>>>> >> > So what you really have is `unique_value<=
T>` and `shared_value<const T>`, with conversions between them. Th=
is also permits you to have a mutable `shared_value<T>` if a user wan=
ts it, rather than enforcing immutability at the interface level. <br>
>>>> >><br>
>>>> >> Would that allow enforcement of non modification =
by an aliasing value? There's two sides to immutability; there's &q=
uot;I can't modify it" and there's "no-one can modify it&=
quot;.<br>
>>>> ><br>
>>>> ><br>
>>>> > Conceptually, it's a value type, so it wouldn'=
;t have aliasing of any form. What would that even mean? Would you be alias=
ing a value with another value? Indeed, the OP excluded aliasing from `cons=
t_shared_ptr`'s interface, since it doesn't make sense.<br>
>>>><br>
>>>> Sorry, I didn't mean aliasing in the sense of creating=
a shared_ptr to a subobject, rather in the general sense of one pointer ha=
ving the same target as another pointer, or one reference having the same r=
eferent as another reference.<br>
>>>><br>
>>>> In your shared_value scheme, a modification to one shared_=
value<T> can be observed by another shared_value with the same target=
.. Can you prevent a shared_value<T const> having the same target as a=
shared_value<T>?<br>
>>><br>
>>><br>
>>> The same way as I showed for `shared_ptr`: make it `const` whe=
n you create the first one.<br>
>>><br>
>>> If you want pure COW semantics from the type I've suggeste=
d, then you make a `shared_value<const T>` at the point of origin. At=
no time do you make a `shared_value<T>`.<br>
>><br>
>><br>
>> But then you can *never* modify it; you can only copy it to a new =
mutable value. Which is great for functional purity, but could also be inef=
ficient.<br>
><br>
><br>
> That's what the OP asked for. You start with `const_shared_ptr` an=
d hand it out to people who can make mutable copies of it.</p>
<p dir=3D"ltr">Yes, but OP also wants to be able to convert it back to muta=
ble form if that can be done safely. </p>
<p dir=3D"ltr">>>> The thing is, I've always thought we should=
have a `value_ptr<T>` type. That is, a type that *certainly* allocat=
es memory for `T`, moves via moving the pointer, but copies itself by copyi=
ng the object by value. This would be useful for cases where `T` is expensi=
ve to move and/or throws on moving.<br>
>>><br>
>>> A `shared_value_ptr<T>` would not be an unreasonable pai=
ring for such a type. And then we could have `shared_value_ptr<const T&g=
t;` serve the needs the OP requires for COW gymnastics, so long as there is=
a conversion from `shared_value_ptr` to `value_ptr` which is permitted to =
avoid a copy if the `shared_value_ptr` moved into it is the last one.<br>
>><br>
>><br>
>> But that conversion would give you a value_ptr<T const>, so =
it would still be immutable even when it should be safe to mutate.<br>
><br>
><br>
> This is perfectly legitimate code:<br>
><br>
> const T t =3D ...;<br>
> T t2 =3D std::move(t);</p>
<p dir=3D"ltr">Legitimate, but it has unexpected semantics; it doesn't =
call the move constructor. </p>
<p dir=3D"ltr">> Why should this not be legitimate:<br>
><br>
> shared_value_ptr<const T> t =3D ...;<br>
> value_ptr<T> t2 =3D std::move(t);<br>
><br>
> The only difference between the two is that the last one can not copy =
the object if `t` is the last owner of that memory.</p>
<p dir=3D"ltr">Well, it wouldn't work if the constructor of shared_valu=
e_ptr<T const> ends up calling new T const, because the pointee would=
be an actually const object. </p>
<p dir=3D"ltr">The implementation would have to remove_const on T before co=
nstructing the pointee, which would inhibit optimization if you didn't =
intend ever to use it mutably.</p>
<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/CAJnLdOYm6mQ2BAA4Ys%3DOwBECTH6ugQcTU4=
Ns5wkxyqozGt%2BTkQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOYm6mQ2=
BAA4Ys%3DOwBECTH6ugQcTU4Ns5wkxyqozGt%2BTkQ%40mail.gmail.com</a>.<br />
--001a1146ed6e768d7a053aed6fb8--
.