Topic: optional_ptr - A smart pointer which optionally


Author: Andrey Semashev <andrey.semashev@gmail.com>
Date: Thu, 24 Sep 2015 19:54:53 +0300
Raw View
On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante
<fmatthew5876@gmail.com> wrote:
> For all resources, we have owners who manage the lifetime of the resource
> and viewers who view the resource. To be correct, all of the viewers have to
> stop using the pointer before the last owner goes out of scope and destroys
> the resource.

If anything, this sounds fragile and dangerous.

But, in case you can easily guarantee that the owner outlives the
viewers, did you consider using unique_ptr with a custom deleter?

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 24 Sep 2015 10:36:36 -0700 (PDT)
Raw View
------=_Part_998_811263287.1443116196920
Content-Type: multipart/alternative;
 boundary="----=_Part_999_744665629.1443116196921"

------=_Part_999_744665629.1443116196921
Content-Type: text/plain; charset=UTF-8



On Thursday, September 24, 2015 at 12:35:28 PM UTC-4, Matthew Fioravante
wrote:
>
> For all resources, we have owners who manage the lifetime of the resource
> and viewers who view the resource. To be correct, all of the viewers have
> to stop using the pointer before the last owner goes out of scope and
> destroys the resource.
>
> For both unique_ptr and shared_ptr, the set of owners and viewers has to
> be decided explicitly ahead of time. This can very limiting because I've
> run into cases where I have types which 99% of the time are viewers
> (because the resource is often shared) but in some rare contexts need to be
> an owner because the object is being used standalone with no external
> entity to manage the ownership.
>

.... This seems to be a problem with how you're thinking of types and
ownerships.

Types do not define ownership. Or at least, not in the way you seem to
mean. What defines ownership is *code*, at compile time.

If I have some function:

void do_something(unique_ptr<T> p);

That function is explicitly claiming ownership of the object it is given.
The fact that it claims ownership is an integral part of what it means to
`do_something`.

If I have this function:

void do_something2(T *p);

It is (by convention) *not* claiming ownership of `p`.

If you want to call `do_something2`, and you have a `unique_ptr<T>`, simply
call `get` to fetch the pointer.

If you have a T* and you want to call `do_something`... you can't. You have
no right to do so. Because you do not own that object, and you therefore
cannot transfer something you don't have.

That's just a good interface.

I'm just having a hard time imagining what a hypothetical `do_something3`
function would actually be doing if it does not statically know if it's
claiming ownership or not.

If the `do_something3` is a free function, one for which the parameter is
not stored beyond its scope, then the concept of ownership is pointless.
Because again, you just pass it a T*. If the caller has a `unique_ptr`, and
is finished with that `unique_ptr` immediately after calling
`do_something2`, they can simply destroy it right after the call.

So this is only meaningful if you have an *object* which may or may not own
some other object it is given. Can you give a more concrete example of an
object that cannot statically know if expects to be given ownership of an
object?

The heavy handed solution to use shared_ptr everywhere. Now everyone is an
> owner. Using shared_ptr adds runtime overhead to manage the reference
> count. The biggest problem with shared_ptr is that once you use it in one
> place, you have to use it everywhere. Everything now must be dynamically
> allocated individually. You can't allocate 20 objects in an array and view
> one of them. You can't create objects on the stack or as a data member.
>

You can in fact do all of those things with `shared_ptr`. Simply provide
the initial shared_ptr<T> with a deleter that doesn't delete it.

Sure, you still have the reference count overhead which now accomplishes
nothing. But other than that, it's a perfectly functional solution.

Essentially, optional_ptr is a move only type that works like
> a variant<T*,unique_ptr<T>>.
>

So why not just use a variant<T*, unique_ptr<T>>? Just create a simple
visitor to get a T* out of it.

Because `unique_ptr` is move only, so too will the `variant` containing it.
It does everything you want, just not quite with the interface you'd prefer.

Not only that, it gives you the flexibility to ask the question: do I
actually have ownership of this object? Your proposed interface doesn't
provide taht facility. Which means that your class can only talk to code
that either itself doesn't know or that takes a T*. It can't call code that
takes a unique_ptr<T>.

Also, remember that `unique_ptr` has options as well. It could take an
array, and it has a deleter type. With the `variant` case, users can
specify options as needed. In your proposed syntax, they can only use the
conceptual equivalent of unique_ptr<T>.

Given that this variant solves your problem adequately, and that your
use-case is fairly niche, I'd say to take the 80% solution and move on.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_999_744665629.1443116196921
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Thursday, September 24, 2015 at 12:35:28 PM UTC=
-4, Matthew Fioravante wrote:<blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div>For all resources, we have=C2=A0owners who manage the =
lifetime of the resource and viewers who view the resource. To be correct, =
all of the viewers have to stop using the pointer before the last owner goe=
s out of scope and destroys the resource.</div><div>=C2=A0</div><div>For bo=
th unique_ptr and shared_ptr, the set of owners and viewers has to be decid=
ed explicitly ahead of time. This can very limiting because I&#39;ve run in=
to cases where I have types which 99% of the time are viewers (because the =
resource is often shared)=C2=A0but in some rare contexts need to be an owne=
r because the object is being used standalone with no external entity to ma=
nage the ownership.</div></div></blockquote><div><br>... This seems to be a=
 problem with how you&#39;re thinking of types and ownerships.<br><br>Types=
 do not define ownership. Or at least, not in the way you seem to mean. Wha=
t defines ownership is <i>code</i>, at compile time.<br><br>If I have some =
function:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
do_something</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">unique_=
ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span></div></code></div><br>That=
 function is explicitly claiming ownership of the object it is given. The f=
act that it claims ownership is an integral part of what it means to `do_so=
mething`.<br><br>If I have this function:<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;"><cod=
e class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> do_something2</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">T </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
);</span></div></code></div><br>It is (by convention) <i>not</i> claiming o=
wnership of `p`.<br><br>If you want to call `do_something2`, and you have a=
 `unique_ptr&lt;T&gt;`, simply call `get` to fetch the pointer.<br><br>If y=
ou have a T* and you want to call `do_something`... you can&#39;t. You have=
 no right to do so. Because you do not own that object, and you therefore c=
annot transfer something you don&#39;t have.<br><br>That&#39;s just a good =
interface.<br><br>I&#39;m just having a hard time imagining what a hypothet=
ical `do_something3` function would actually be doing if it does not static=
ally know if it&#39;s claiming ownership or not.<br><br>If the `do_somethin=
g3` is a free function, one for which the parameter is not stored beyond it=
s scope, then the concept of ownership is pointless. Because again, you jus=
t pass it a T*. If the caller has a `unique_ptr`, and is finished with that=
 `unique_ptr` immediately after calling `do_something2`, they can simply de=
stroy it right after the call.<br><br>So this is only meaningful if you hav=
e an <i>object</i> which may or may not own some other object it is given. =
Can you give a more concrete example of an object that cannot statically kn=
ow if expects to be given ownership of an object?<br><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> </div><div>The heav=
y handed solution to use shared_ptr everywhere. Now everyone is an owner. U=
sing shared_ptr adds runtime overhead to manage the reference count. The bi=
ggest problem with shared_ptr is that once you use it in one place, you hav=
e to use it everywhere. Everything now must be dynamically allocated indivi=
dually. You can&#39;t allocate 20 objects in an array and view one of them.=
 You can&#39;t create objects on the stack or as a data member.</div></div>=
</blockquote><div><br>You can in fact do all of those things with `shared_p=
tr`. Simply provide the initial shared_ptr&lt;T&gt; with a deleter that doe=
sn&#39;t delete it.<br><br>Sure, you still have the reference count overhea=
d which now accomplishes nothing. But other than that, it&#39;s a perfectly=
 functional solution.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div></div><div>Essentially, optional_ptr is a move =
only type that works like a=C2=A0variant&lt;T*,unique_ptr&lt;T&gt;&gt;.</di=
v></div></blockquote><div><br>So why not just use a variant&lt;T*, unique_p=
tr&lt;T&gt;&gt;? Just create a simple visitor to get a T* out of it.<br><br=
>Because `unique_ptr` is move only, so too will the `variant` containing it=
.. It does everything you want, just not quite with the interface you&#39;d =
prefer.<br><br>Not only that, it gives you the flexibility to ask the quest=
ion: do I actually have ownership of this object? Your proposed interface d=
oesn&#39;t provide taht facility. Which means that your class can only talk=
 to code that either itself doesn&#39;t know or that takes a T*. It can&#39=
;t call code that takes a unique_ptr&lt;T&gt;.<br><br>Also, remember that `=
unique_ptr` has options as well. It could take an array, and it has a delet=
er type. With the `variant` case, users can specify options as needed. In y=
our proposed syntax, they can only use the conceptual equivalent of unique_=
ptr&lt;T&gt;.<br><br>Given that this variant solves your problem adequately=
, and that your use-case is fairly niche, I&#39;d say to take the 80% solut=
ion and move on.<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_999_744665629.1443116196921--
------=_Part_998_811263287.1443116196920--

.


Author: "'Jeffrey Yasskin' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 10:53:26 -0700
Raw View
--001a1141ef3c9eb63b052081e9f1
Content-Type: text/plain; charset=UTF-8

We have an optional ownership pattern at Google, involving storing an enum
next to the pointer. It's fairly bad, but it gets the job done. I suspect
an optional-ownership class isn't the most important thing the committee
could be spending time on, but it's not crazy.

Using unique_ptr deleters for this is clever, which is as much criticism as
it is praise. Having a deleter that doesn't delete makes uses of unique_ptr
harder to read, and to some extent is an indication that move-only types
are too hard to write.

Jeffrey

On Thu, Sep 24, 2015 at 9:35 AM, Matthew Fioravante <fmatthew5876@gmail.com>
wrote:

> For all resources, we have owners who manage the lifetime of the resource
> and viewers who view the resource. To be correct, all of the viewers have
> to stop using the pointer before the last owner goes out of scope and
> destroys the resource.
>
> For both unique_ptr and shared_ptr, the set of owners and viewers has to
> be decided explicitly ahead of time. This can very limiting because I've
> run into cases where I have types which 99% of the time are viewers
> (because the resource is often shared) but in some rare contexts need to be
> an owner because the object is being used standalone with no external
> entity to manage the ownership.
>
> The heavy handed solution to use shared_ptr everywhere. Now everyone is an
> owner. Using shared_ptr adds runtime overhead to manage the reference
> count. The biggest problem with shared_ptr is that once you use it in one
> place, you have to use it everywhere. Everything now must be dynamically
> allocated individually. You can't allocate 20 objects in an array and view
> one of them. You can't create objects on the stack or as a data member.
> Forcing individual dynamic allocation is a performance killer. We use C++
> because we need to be fast and a big part of being fast beings avoiding
> allocations or failing that, batching them into fewer allocations of large
> contiguous cache friendly chunks.
>
> The solution I'm toying with now is something called optional_ptr. Maybe
> its not such a great name because it could be confused with std::optional
> but lets leave bikeshedding aside for now.
>
> Essentially, optional_ptr is a move only type that works like
> a variant<T*,unique_ptr<T>>. You can construct it with a raw pointer for
> non-owning semantics or construct it with a unique_ptr to get owning
> semantics.
>
> The naive implementation of optional_ptr is to use T* and a bool, but for
> any type with alignof(T) > 1, you can actually store the ownership bit
> in lowest bit of the pointer itself since that bit will always be 0 due to
> alignment. The result is that OptionalPtr has minimal runtime overhead over
> unique_ptr/T* and for most types zero space overhead as well.
>
> Using optional_ptr means an entity has the flexibility to be either an
> owner or a viewer. Move only ensures unique ownership just like unique_ptr.
>
> Here is a sketch of what it might look like:
>
> template <typename T>
> class optional_ptr {
> public:
>   optional_ptr() = default;
>   optional_ptr(T* p) : _p(p), _own(false) {}
>   optional_ptr(unique_ptr<T> p) : _p(p.release()), _own(true) {}
>   ~optional_ptr() { if(_own) delete p; }
>
>   optional_ptr(const optional_ptr<T>&) = delete;
>   optional_ptr<T>& operator=(const optional_ptr<T>&) = delete;
>
>   optional_ptr(optional_ptr<T>&&) noexcept;
>   optional_ptr<T>& operator=(optional_ptr<T>&&) noexcept;
>
>   bool owns() const { return _own; }
>   T* get() const { return _p; }
>   T* release() noexcept { auto* p = _p; _own = false; _p = nullptr; return
> p; }
>   void reset(T* p);
>   void reset(unique_ptr<T> p);
>
>   //etc...
> private:
>   T* _p = nullptr;
>   bool _own = false;
> };
>
> How have you dealt with the problem of having a viewer which sometimes
> needs to be an owner? Do you see this as a valid problem that needs
> addressing or an anti-pattern?
>
>
>
>
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a1141ef3c9eb63b052081e9f1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">We have an optional ownership pattern at Google, involving=
 storing an enum next to the pointer. It&#39;s fairly bad, but it gets the =
job done. I suspect an optional-ownership class isn&#39;t the most importan=
t thing the committee could be spending time on, but it&#39;s not crazy.<di=
v><br></div><div>Using unique_ptr deleters for this is clever, which is as =
much criticism as it is praise. Having a deleter that doesn&#39;t delete ma=
kes uses of unique_ptr harder to read, and to some extent is an indication =
that move-only types are too hard to write.<br><div class=3D"gmail_extra"><=
br></div><div class=3D"gmail_extra">Jeffrey</div><div class=3D"gmail_extra"=
><br><div class=3D"gmail_quote">On Thu, Sep 24, 2015 at 9:35 AM, Matthew Fi=
oravante <span dir=3D"ltr">&lt;<a href=3D"mailto:fmatthew5876@gmail.com" ta=
rget=3D"_blank" class=3D"cremed">fmatthew5876@gmail.com</a>&gt;</span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>For all resource=
s, we have=C2=A0owners who manage the lifetime of the resource and viewers =
who view the resource. To be correct, all of the viewers have to stop using=
 the pointer before the last owner goes out of scope and destroys the resou=
rce.</div><div>=C2=A0</div><div>For both unique_ptr and shared_ptr, the set=
 of owners and viewers has to be decided explicitly ahead of time. This can=
 very limiting because I&#39;ve run into cases where I have types which 99%=
 of the time are viewers (because the resource is often shared)=C2=A0but in=
 some rare contexts need to be an owner because the object is being used st=
andalone with no external entity to manage the ownership.</div><div>=C2=A0<=
/div><div>The heavy handed solution to use shared_ptr everywhere. Now every=
one is an owner. Using shared_ptr adds runtime overhead to manage the refer=
ence count. The biggest problem with shared_ptr is that once you use it in =
one place, you have to use it everywhere. Everything now must be dynamicall=
y allocated individually. You can&#39;t allocate 20 objects in an array and=
 view one of them. You can&#39;t create objects on the stack or as a data m=
ember. Forcing individual dynamic allocation is a performance killer. We us=
e C++ because we need to be fast and a big part of being fast beings avoidi=
ng allocations or failing that, batching them into fewer allocations of lar=
ge contiguous cache friendly chunks.</div><div>=C2=A0</div><div>The solutio=
n I&#39;m toying with now=C2=A0is something called optional_ptr. Maybe its =
not such a great name because it could be confused with std::optional but l=
ets leave bikeshedding aside for now.</div><div>=C2=A0</div><div>Essentiall=
y, optional_ptr is a move only type that works like a=C2=A0variant&lt;T*,un=
ique_ptr&lt;T&gt;&gt;. You can construct it with a raw pointer for non-owni=
ng semantics or construct it with a unique_ptr to get owning semantics. </d=
iv><div>=C2=A0</div><div>The naive implementation of optional_ptr is to use=
 T* and a bool, but for any type with alignof(T) &gt; 1, you can actually s=
tore the ownership bit in=C2=A0lowest bit of the pointer itself since that =
bit will always be 0 due to alignment. The result is that OptionalPtr has m=
inimal runtime overhead over unique_ptr/T* and for most types zero space ov=
erhead as well.</div><div>=C2=A0</div><div>Using optional_ptr means an enti=
ty=C2=A0has the flexibility to be=C2=A0either an owner or a viewer. Move on=
ly ensures unique ownership just like unique_ptr.</div><div>=C2=A0</div><di=
v>Here is=C2=A0a sketch of what it might look like:</div><div><code></code>=
=C2=A0</div><div><code><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(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:r=
gb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)"> T</span><span=
 style=3D"color:rgb(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0,0)"=
><br></span><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"c=
olor:rgb(0,0,0)"> optional_ptr </span><span style=3D"color:rgb(102,102,0)">=
{</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(0,0,136)">public</span><span style=3D"color:rgb(102,102,0)">:</span><span=
 style=3D"color:rgb(0,0,0)"><br>=C2=A0 optional_ptr</span><span style=3D"co=
lor:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> </span><span=
 style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)">=
 </span><span style=3D"color:rgb(0,0,136)">default</span><span style=3D"col=
or:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 opti=
onal_ptr</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"=
color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">*</span><spa=
n style=3D"color:rgb(0,0,0)"> p</span><span style=3D"color:rgb(102,102,0)">=
)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(1=
02,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> _p</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">p</span>=
<span style=3D"color:rgb(102,102,0)">),</span><span style=3D"color:rgb(0,0,=
0)"> _own</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D=
"color:rgb(0,0,136)">false</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(102,10=
2,0)">{}</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 optional_ptr</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,=
0,0)">unique_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;</span><spa=
n style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&=
gt;</span><span style=3D"color:rgb(0,0,0)"> p</span><span style=3D"color:rg=
b(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> _p</spa=
n><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0=
,0)">p</span><span style=3D"color:rgb(102,102,0)">.</span><span style=3D"co=
lor:rgb(0,0,0)">release</span><span style=3D"color:rgb(102,102,0)">()),</sp=
an><span style=3D"color:rgb(0,0,0)"> _own</span><span style=3D"color:rgb(10=
2,102,0)">(</span><span style=3D"color:rgb(0,0,136)">true</span><span style=
=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(102,102,0)">{}</span><span style=3D"color:rgb(0,0,=
0)"><br>=C2=A0 </span><span style=3D"color:rgb(102,102,0)">~</span><span st=
yle=3D"color:rgb(0,0,0)">optional_ptr</span><span style=3D"color:rgb(102,10=
2,0)">()</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(0,0,136)">if</span><span style=3D"color:rgb(102,102,0)">(<=
/span><span style=3D"color:rgb(0,0,0)">_own</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)">delete</span><span style=3D"color:rgb(0,0,0)"> p</span=
><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"col=
or:rgb(0,0,0)"><br><br>=C2=A0 optional_ptr</span><span style=3D"color:rgb(1=
02,102,0)">(</span><span style=3D"color:rgb(0,0,136)">const</span><span sty=
le=3D"color:rgb(0,0,0)"> optional_ptr</span><span style=3D"color:rgb(102,10=
2,0)">&lt;</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"co=
lor:rgb(102,102,0)">&gt;&amp;)</span><span style=3D"color:rgb(0,0,0)"> </sp=
an><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delete</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=
=A0 optional_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;</span><spa=
n style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&=
gt;&amp;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(0,0,136)">operator</span><span style=3D"color:rgb(102,102,0)">=3D(</s=
pan><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb=
(0,0,0)"> optional_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;</spa=
n><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102=
,0)">&gt;&amp;)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,0,136)">delete</span><span style=3D"color:rgb(=
102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 optiona=
l_ptr</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"col=
or:rgb(0,0,0)">optional_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;=
</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(10=
2,102,0)">&gt;&amp;&amp;)</span><span style=3D"color:rgb(0,0,0)"> noexcept<=
/span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 optional_ptr</span><span style=3D"color:rgb(102,102,0)"=
>&lt;</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"color:r=
gb(102,102,0)">&gt;&amp;</span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(0,0,136)">operator</span><span style=3D"color:rgb(102=
,102,0)">=3D(</span><span style=3D"color:rgb(0,0,0)">optional_ptr</span><sp=
an style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,0=
)">T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp;&amp;)</span><span=
 style=3D"color:rgb(0,0,0)"> noexcept</span><span style=3D"color:rgb(102,10=
2,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 <br>=C2=A0 </span=
><span style=3D"color:rgb(0,0,136)">bool</span><span style=3D"color:rgb(0,0=
,0)"> owns</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)">const</spa=
n><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102=
,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> _own</span><sp=
an style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)">=
 </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 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)"=
>get</span><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">const</span><span=
 style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{<=
/span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0=
,136)">return</span><span style=3D"color:rgb(0,0,0)"> _p</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0=
)"><br>=C2=A0 T</span><span style=3D"color:rgb(102,102,0)">*</span><span st=
yle=3D"color:rgb(0,0,0)"> release</span><span style=3D"color:rgb(102,102,0)=
">()</span><span style=3D"color:rgb(0,0,0)"> noexcept </span><span style=3D=
"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(102,102=
,0)">*</span><span style=3D"color:rgb(0,0,0)"> p </span><span style=3D"colo=
r:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> _p</span><spa=
n style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> =
_own </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">false</span><sp=
an style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)">=
 _p </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"co=
lor:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">nullptr</span><s=
pan style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"=
> </span><span style=3D"color:rgb(0,0,136)">return</span><span style=3D"col=
or:rgb(0,0,0)"> p</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">}</=
span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"colo=
r:rgb(0,0,136)">void</span><span style=3D"color:rgb(0,0,0)"> reset</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)"=
>T</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:=
rgb(0,0,0)"> p</span><span style=3D"color:rgb(102,102,0)">);</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136=
)">void</span><span style=3D"color:rgb(0,0,0)"> reset</span><span style=3D"=
color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">unique_ptr</=
span><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:r=
gb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&gt;</span><span st=
yle=3D"color:rgb(0,0,0)"> p</span><span style=3D"color:rgb(102,102,0)">);</=
span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 </span><span style=3D"=
color:rgb(136,0,0)">//etc...</span><span style=3D"color:rgb(0,0,0)"><br></s=
pan><span style=3D"color:rgb(0,0,136)">private</span><span style=3D"color:r=
gb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 T</span>=
<span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0=
)"> _p </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">nullptr</span=
><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,=
0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">bool</span><span s=
tyle=3D"color:rgb(0,0,0)"> _own </span><span style=3D"color:rgb(102,102,0)"=
>=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(0,0,136)">false</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"> <br></span><span style=3D"color:rgb(102,102,0)"=
>};</span><span style=3D"color:rgb(0,0,0)"><br></span></div></code></div><b=
r>How have you dealt with the problem of having a viewer which sometimes ne=
eds to be an owner? Do you see this as a valid problem that needs addressin=
g or an anti-pattern?</code></div><span class=3D"HOEnZb"><font color=3D"#88=
8888"><code><div><span style=3D"color:rgb(0,0,136)"></span>=C2=A0</div></co=
de><br><div>=C2=A0</div><div>=C2=A0</div></font></span></div><span class=3D=
"HOEnZb"><font color=3D"#888888">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank" class=3D"cremed">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" class=3D"cremed">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" class=3D"cremed">http://groups.google.com=
/a/isocpp.org/group/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a1141ef3c9eb63b052081e9f1--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Thu, 24 Sep 2015 11:21:30 -0700 (PDT)
Raw View
------=_Part_789_1836315049.1443118891014
Content-Type: multipart/alternative;
 boundary="----=_Part_790_452308375.1443118891015"

------=_Part_790_452308375.1443118891015
Content-Type: text/plain; charset=UTF-8


On Thursday, September 24, 2015 at 12:54:55 PM UTC-4, Andrey Semashev wrote:
>
> On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante
> <*fmatth...@gmail.com* <javascript:>> wrote:
> > For all resources, we have owners who manage the lifetime of the resource
> > and viewers who view the resource. To be correct, all of the viewers
> have to
> > stop using the pointer before the last owner goes out of scope and
> destroys
> > the resource.
>
> If anything, this sounds fragile and dangerous.


This was my concern as well and what I anticipate to be the biggest
argument against this idiom. However I'm not yet entirely convinced that
its any less dangerous to the situation where you have a unique_ptr owned
by A and viewed by B as a T*. Its up to the programmer to ensure that B's
lifetime is within A's lifetime.

If someone can identify a situation where optional_ptr is much more
dangerous than unique_ptr/T* that would be really helpful.



>
> But, in case you can easily guarantee that the owner outlives the
> viewers, did you consider using unique_ptr with a custom deleter?


 I'm not sure how a custom deleter would help. If the deleter does nothing,
then you just have T*, if the deleter conditionally deletes the object
based on a boolean state, you have my optional_ptr. A reusable common
pattern should have a name, not be a backwards hack on a unique_ptr deleter.



On Thursday, September 24, 2015 at 1:36:37 PM UTC-4, Nicol Bolas wrote:
>
>
>
> On Thursday, September 24, 2015 at 12:35:28 PM UTC-4, Matthew Fioravante
> wrote:
>>
>> For all resources, we have owners who manage the lifetime of the resource
>> and viewers who view the resource. To be correct, all of the viewers have
>> to stop using the pointer before the last owner goes out of scope and
>> destroys the resource.
>>
>> For both unique_ptr and shared_ptr, the set of owners and viewers has to
>> be decided explicitly ahead of time. This can very limiting because I've
>> run into cases where I have types which 99% of the time are viewers
>> (because the resource is often shared) but in some rare contexts need to be
>> an owner because the object is being used standalone with no external
>> entity to manage the ownership.
>>
>
> ... This seems to be a problem with how you're thinking of types and
> ownerships.
>
> Types do not define ownership. Or at least, not in the way you seem to
> mean. What defines ownership is *code*, at compile time.
>

Not sure I agree, unless I'm misunderstanding you somehow. If a type stores
an object by unique_ptr or shared_ptr, that type defines ownership of the
resource. If the type stores by T*, he defines non-ownership.



>
> If I have some function:
>
> void do_something(unique_ptr<T> p);
>
> That function is explicitly claiming ownership of the object it is given.
> The fact that it claims ownership is an integral part of what it means to
> `do_something`.
>
> If I have this function:
>
> void do_something2(T *p);
>
> It is (by convention) *not* claiming ownership of `p`.
>
> If you want to call `do_something2`, and you have a `unique_ptr<T>`,
> simply call `get` to fetch the pointer.
>
> If you have a T* and you want to call `do_something`... you can't. You
> have no right to do so. Because you do not own that object, and you
> therefore cannot transfer something you don't have.
>
> That's just a good interface.
>
> I'm just having a hard time imagining what a hypothetical `do_something3`
> function would actually be doing if it does not statically know if it's
> claiming ownership or not.
>

If a function needs to take ownership of a resource, it gets a unique_ptr.
If it needs to use/view the resource someone else owns, it gets T*. If it
needs to view/use the resource and also allow optionally taking ownership,
use an optional_ptr. What choice was taken is clearly documented at the
call site because you have to construct optional_ptr by moving in
a unique_ptr if you want it to be an owner.

I'm using unique_ptr in my code a lot and I'm often having to create extra
structures just to store the unique_ptr's when the actual consumer in this
context only accepts a T*.



>
> If the `do_something3` is a free function, one for which the parameter is
> not stored beyond its scope, then the concept of ownership is pointless.
>

Of course, for a function that is not a sink you should never pass any kind
of smart pointer. That seems like a general guideline outside of the scope
of this discussion.


> Because again, you just pass it a T*. If the caller has a `unique_ptr`,
> and is finished with that `unique_ptr` immediately after calling
> `do_something2`, they can simply destroy it right after the call.
>
> So this is only meaningful if you have an *object* which may or may not
> own some other object it is given. Can you give a more concrete example of
> an object that cannot statically know if expects to be given ownership of
> an object?
>

Sure, one real example I have is a pipeline. lets say we have pipeline that
manages 3 data streams A, B, and C with a configurable number of stages.
Each stage can apply some transformation to A, B, or C or just pass it
along. When a stage needs to modify a stream, he gets a view of the
previous stream, allocates and takes ownership of a new one, and then
applies his transformations to convert A -> A`. If he does not need to
modify a stream, he just passes along a view of it.

This pattern can be accomplished using shared_ptr but again its unecessary.
It can also be accomplished with unique_ptr but then each stage has to make
a copy of each stream and copy the data even if he does not modify it.
Every pipeline stage that has a non-owning pointer is guaranteed that the
pointer is owned by a previous stage. When the stages are destroyed in
reverse order, all resources are released correctly with epsilon overhead.



>
> The heavy handed solution to use shared_ptr everywhere. Now everyone is an
>> owner. Using shared_ptr adds runtime overhead to manage the reference
>> count. The biggest problem with shared_ptr is that once you use it in one
>> place, you have to use it everywhere. Everything now must be dynamically
>> allocated individually. You can't allocate 20 objects in an array and view
>> one of them. You can't create objects on the stack or as a data member.
>>
>
> You can in fact do all of those things with `shared_ptr`. Simply provide
> the initial shared_ptr<T> with a deleter that doesn't delete it.
>
> Sure, you still have the reference count overhead which now accomplishes
> nothing. But other than that, it's a perfectly functional solution.
>

Aside from the wasted reference count overhead this seems very brittle. Its
very easy to construct a shared_ptr and forget to pass in that noop
deleter.



>
> Essentially, optional_ptr is a move only type that works like
>> a variant<T*,unique_ptr<T>>.
>>
>
> So why not just use a variant<T*, unique_ptr<T>>? Just create a simple
> visitor to get a T* out of it.
>
> Because `unique_ptr` is move only, so too will the `variant` containing
> it. It does everything you want, just not quite with the interface you'd
> prefer.
>

Again for a reusable pattern, I'd rather the thing had a name. Also variant
can't take advantage of the optimization I mentioned of storing the bit in
the pointer. Having a smart pointer type that stores { T*, bool } is
very bad because sizeof() will be equal to 2 * T* due to padding. If you
have a lot of these you will waste of a lot of valuable cache line space.


>
> Not only that, it gives you the flexibility to ask the question: do I
> actually have ownership of this object? Your proposed interface doesn't
> provide taht facility.
>

Sure you can, the owns() method tells you whether or not you have it, but
I'm not sure thats actually very useful in practice.


> Which means that your class can only talk to code that either itself
> doesn't know or that takes a T*.
>

This is the intended use case. Once I've given up static proof that the
object owns the resource I can't get it back. Once you reduce from
unique_ptr to optional_ptr can only stay at the optional_ptr level
or reduce further to viewing via T*.



> It can't call code that takes a unique_ptr<T>.
>

Its not designed to ever call code that takes a unique_ptr. You
can't blindly pass a T* someone else owns to a unique_ptr. You also can't
pass something that dynamically may or may not own to something that
staticly always owns.

If you really had to, you could check the owns() flag and pass it
mechanically using release() but I would consider this use a huge
anti-pattern hack.


>
> Also, remember that `unique_ptr` has options as well. It could take an
> array, and it has a deleter type. With the `variant` case, users can
> specify options as needed. In your proposed syntax, they can only use the
> conceptual equivalent of unique_ptr<T>.
>

optional_ptr can have deleters and support arrays too. I've left all that
out for now because its not central to the first question of whether this
is actually a good pattern and second whether it has a place in the
standard library.


>
> Given that this variant solves your problem adequately, and that your
> use-case is fairly niche, I'd say to take the 80% solution and move on.
>


--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_790_452308375.1443118891015
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Thursday, September 24, 2015 at 12:54:55 PM UTC-4, =
Andrey Semashev wrote:<blockquote style=3D"margin: 0px 0px 0px 0.8ex; paddi=
ng-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px=
; border-left-style: solid;" class=3D"gmail_quote">On Thu, Sep 24, 2015 at =
7:35 PM, Matthew Fioravante<br>&lt;<a onmousedown=3D"this.href=3D&#39;javas=
cript:&#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;retu=
rn true;" href=3D"javascript:" rel=3D"nofollow" target=3D"_blank" gdf-obfus=
cated-mailto=3D"uwb7kxd9CAAJ"><u><font color=3D"#000080">fmatth...@gmail.co=
m</font></u></a>&gt; wrote:<br>&gt; For all resources, we have owners who m=
anage the lifetime of the resource<br>&gt; and viewers who view the resourc=
e. To be correct, all of the viewers have to<br>&gt; stop using the pointer=
 before the last owner goes out of scope and destroys<br>&gt; the resource.=
<br><br>If anything, this sounds fragile and dangerous.</blockquote><div>=
=C2=A0</div><div>This was my concern as well and what I anticipate to be th=
e biggest argument against this idiom. However I&#39;m not yet entirely con=
vinced that its any less dangerous to the situation where you have a unique=
_ptr=C2=A0owned by A and viewed by B as a T*.=C2=A0Its up to the=C2=A0progr=
ammer to ensure that B&#39;s lifetime is within A&#39;s lifetime.</div><div=
>=C2=A0</div><div>If someone can identify a situation where optional_ptr is=
 much more dangerous than unique_ptr/T* that would be really helpful.</div>=
<div>=C2=A0</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px =
0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-lef=
t-width: 1px; border-left-style: solid;" class=3D"gmail_quote"><br>But, in =
case you can easily guarantee that the owner outlives the<br>viewers, did y=
ou consider using unique_ptr with a custom deleter?</blockquote><div>=C2=A0=
</div><div>=C2=A0I&#39;m not sure how a custom deleter would help. If the d=
eleter does nothing, then you just have T*, if the deleter conditionally de=
letes the object based on a boolean state, you have my optional_ptr. A reus=
able common pattern should have a name, not be a backwards hack on a unique=
_ptr deleter.</div><div>=C2=A0</div><div>=C2=A0</div><br>On Thursday, Septe=
mber 24, 2015 at 1:36:37 PM UTC-4, Nicol Bolas wrote:<blockquote style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;" class=3D"gmail_=
quote"><div dir=3D"ltr"><br><br>On Thursday, September 24, 2015 at 12:35:28=
 PM UTC-4, Matthew Fioravante wrote:<blockquote style=3D"margin: 0px 0px 0p=
x 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-l=
eft-width: 1px; border-left-style: solid;" class=3D"gmail_quote"><div dir=
=3D"ltr"><div>For all resources, we have=C2=A0owners who manage the lifetim=
e of the resource and viewers who view the resource. To be correct, all of =
the viewers have to stop using the pointer before the last owner goes out o=
f scope and destroys the resource.</div><div>=C2=A0</div><div>For both uniq=
ue_ptr and shared_ptr, the set of owners and viewers has to be decided expl=
icitly ahead of time. This can very limiting because I&#39;ve run into case=
s where I have types which 99% of the time are viewers (because the resourc=
e is often shared)=C2=A0but in some rare contexts need to be an owner becau=
se the object is being used standalone with no external entity to manage th=
e ownership.</div></div></blockquote><div><br>... This seems to be a proble=
m with how you&#39;re thinking of types and ownerships.<br><br>Types do not=
 define ownership. Or at least, not in the way you seem to mean. What defin=
es ownership is <i>code</i>, at compile time.</div></div></blockquote><div>=
=C2=A0</div><div>Not sure I agree, unless I&#39;m misunderstanding you some=
how. If a type stores an object by unique_ptr or shared_ptr, that type defi=
nes ownership of the resource. If=C2=A0the=C2=A0type stores by T*, he defin=
es non-ownership.=C2=A0</div><div>=C2=A0</div><div>=C2=A0</div><blockquote =
style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: r=
gb(204, 204, 204); border-left-width: 1px; border-left-style: solid;" class=
=3D"gmail_quote"><div dir=3D"ltr"><div><br>If I have some function:<br><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);">void</span><span style=3D"color: rgb(0, 0, 0);"> do_something=
</span><span style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"colo=
r: rgb(0, 0, 0);">unique_ptr</span><span style=3D"color: rgb(102, 102, 0);"=
>&lt;</span><span style=3D"color: rgb(0, 0, 0);">T</span><span style=3D"col=
or: rgb(102, 102, 0);">&gt;</span><span style=3D"color: rgb(0, 0, 0);"> p</=
span><span style=3D"color: rgb(102, 102, 0);">);</span></div></code></div><=
br>That function is explicitly claiming ownership of the object it is given=
.. The fact that it claims ownership is an integral part of what it means to=
 `do_something`.<br><br>If I have this function:<br><br><div style=3D"borde=
r: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: r=
gb(250, 250, 250);"><code><div><span style=3D"color: rgb(0, 0, 136);">void<=
/span><span style=3D"color: rgb(0, 0, 0);"> do_something2</span><span style=
=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(0, 0, 0);">=
T </span><span style=3D"color: rgb(102, 102, 0);">*</span><span style=3D"co=
lor: rgb(0, 0, 0);">p</span><span style=3D"color: rgb(102, 102, 0);">);</sp=
an></div></code></div><br>It is (by convention) <i>not</i> claiming ownersh=
ip of `p`.<br><br>If you want to call `do_something2`, and you have a `uniq=
ue_ptr&lt;T&gt;`, simply call `get` to fetch the pointer.<br><br>If you hav=
e a T* and you want to call `do_something`... you can&#39;t. You have no ri=
ght to do so. Because you do not own that object, and you therefore cannot =
transfer something you don&#39;t have.<br><br>That&#39;s just a good interf=
ace.<br><br>I&#39;m just having a hard time imagining what a hypothetical `=
do_something3` function would actually be doing if it does not statically k=
now if it&#39;s claiming ownership or not.</div></div></blockquote><div>=C2=
=A0</div><div>If a function needs to=C2=A0take ownership of a resource, it=
=C2=A0gets a=C2=A0unique_ptr. If it needs to use/view the resource someone =
else owns, it gets T*. If it needs to view/use the resource and also allow =
optionally taking ownership, use an optional_ptr.=C2=A0What choice was take=
n is clearly documented at the call site because you have to construct opti=
onal_ptr=C2=A0by moving in a=C2=A0unique_ptr if you want it to be an owner.=
</div><div>=C2=A0</div><div>I&#39;m using unique_ptr in my code a lot and I=
&#39;m often having to create extra structures just to store the unique_ptr=
&#39;s when the actual consumer in this context only accepts a T*.</div><di=
v>=C2=A0</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8=
ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-w=
idth: 1px; border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr=
"><div><br>If the `do_something3` is a free function, one for which the par=
ameter is not stored beyond its scope, then the concept of ownership is poi=
ntless. </div></div></blockquote><div>=C2=A0</div><div>Of course, for a fun=
ction that is not a sink you should never pass any kind of smart pointer. T=
hat seems like a general guideline outside of the scope of this discussion.=
</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; padd=
ing-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1p=
x; border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"><div>B=
ecause again, you just pass it a T*. If the caller has a `unique_ptr`, and =
is finished with that `unique_ptr` immediately after calling `do_something2=
`, they can simply destroy it right after the call.<br><br>So this is only =
meaningful if you have an <i>object</i> which may or may not own some other=
 object it is given. Can you give a more concrete example of an object that=
 cannot statically know if expects to be given ownership of an object?</div=
></div></blockquote><div>=C2=A0</div><div>Sure, one=C2=A0real example I hav=
e is a pipeline. lets say we have pipeline=C2=A0that manages=C2=A03 data st=
reams A, B, and C with a configurable number of stages. Each stage can=C2=
=A0apply some transformation to=C2=A0A, B, or C or just pass it along. When=
 a stage needs to modify a stream, he gets a view of the previous stream, a=
llocates and takes ownership of a new one, and then applies his transformat=
ions to convert A -&gt; A`. If he does not need to modify a stream, he just=
 passes along a view of it.</div><div>=C2=A0</div><div>This pattern can be =
accomplished using shared_ptr but again its unecessary. It can also be acco=
mplished with unique_ptr but then each stage has to make a copy of each str=
eam and copy the data even if he does not modify it. Every pipeline stage t=
hat has a non-owning pointer is guaranteed that the pointer is owned by a p=
revious stage. When the stages are destroyed in reverse order, all resource=
s are released correctly with epsilon overhead.</div><div>=C2=A0</div><div>=
=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1=
ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-l=
eft-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"><div><br></div><b=
lockquote style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-lef=
t-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: sol=
id;" class=3D"gmail_quote"><div dir=3D"ltr"><div> </div><div>The heavy hand=
ed solution to use shared_ptr everywhere. Now everyone is an owner. Using s=
hared_ptr adds runtime overhead to manage the reference count. The biggest =
problem with shared_ptr is that once you use it in one place, you have to u=
se it everywhere. Everything now must be dynamically allocated individually=
.. You can&#39;t allocate 20 objects in an array and view one of them. You c=
an&#39;t create objects on the stack or as a data member.</div></div></bloc=
kquote><div><br>You can in fact do all of those things with `shared_ptr`. S=
imply provide the initial shared_ptr&lt;T&gt; with a deleter that doesn&#39=
;t delete it.<br><br>Sure, you still have the reference count overhead whic=
h now accomplishes nothing. But other than that, it&#39;s a perfectly funct=
ional solution.</div></div></blockquote><div>=C2=A0</div><div>Aside from th=
e wasted reference count overhead this seems very brittle. Its very easy to=
 construct a shared_ptr and forget to pass in that noop deleter.=C2=A0</div=
><div>=C2=A0</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px=
 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-le=
ft-width: 1px; border-left-style: solid;" class=3D"gmail_quote"><div dir=3D=
"ltr"><div><br></div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; paddin=
g-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px;=
 border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"><div></d=
iv><div>Essentially, optional_ptr is a move only type that works like a=C2=
=A0variant&lt;T*,unique_ptr&lt;T&gt;&gt;.</div></div></blockquote><div><br>=
So why not just use a variant&lt;T*, unique_ptr&lt;T&gt;&gt;? Just create a=
 simple visitor to get a T* out of it.<br><br>Because `unique_ptr` is move =
only, so too will the `variant` containing it. It does everything you want,=
 just not quite with the interface you&#39;d prefer.</div></div></blockquot=
e><div>=C2=A0</div><div>Again for a reusable pattern, I&#39;d rather the th=
ing had a name. Also variant can&#39;t take advantage of the optimization I=
 mentioned of storing the bit in the pointer. Having a=C2=A0smart pointer t=
ype that stores { T*, bool }=C2=A0is very=C2=A0bad because=C2=A0sizeof() wi=
ll be equal to 2 *=C2=A0T* due to padding.=C2=A0If you have a lot of these =
you will waste of a lot of valuable=C2=A0cache line space. </div><div>=C2=
=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex;=
 border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left=
-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"><div><br>Not only th=
at, it gives you the flexibility to ask the question: do I actually have ow=
nership of this object? Your proposed interface doesn&#39;t provide taht fa=
cility. </div></div></blockquote><div>=C2=A0</div><div>Sure you can, the ow=
ns() method tells you whether or not you have it, but I&#39;m not sure that=
s actually very useful in practice.</div><div>=C2=A0</div><blockquote style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;" class=3D"g=
mail_quote"><div dir=3D"ltr"><div>Which means that your class can only talk=
 to code that either itself doesn&#39;t know or that takes a T*. </div></di=
v></blockquote><div>=C2=A0</div><div>This is the intended use case. Once I&=
#39;ve given up static proof that the object owns the resource I can&#39;t =
get it back. Once you=C2=A0reduce from unique_ptr to optional_ptr can only =
stay at the optional_ptr level or=C2=A0reduce further to viewing via T*.</d=
iv><div>=C2=A0</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0=
px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-=
left-width: 1px; border-left-style: solid;" class=3D"gmail_quote"><div dir=
=3D"ltr"><div>It can&#39;t call code that takes a unique_ptr&lt;T&gt;.</div=
></div></blockquote><div>=C2=A0</div><div>Its not designed to ever call cod=
e that takes a=C2=A0unique_ptr. You can&#39;t=C2=A0blindly pass=C2=A0a T* s=
omeone else owns=C2=A0to a unique_ptr.=C2=A0You also can&#39;t pass somethi=
ng that dynamically may or may not own to something that staticly=C2=A0alwa=
ys owns.</div><div>=C2=A0</div><div>If you really had to, you could check t=
he owns() flag and pass it mechanically using release()=C2=A0but I would co=
nsider this use a huge anti-pattern hack.</div><div>=C2=A0</div><blockquote=
 style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: =
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;" clas=
s=3D"gmail_quote"><div dir=3D"ltr"><div><br>Also, remember that `unique_ptr=
` has options as well. It could take an array, and it has a deleter type. W=
ith the `variant` case, users can specify options as needed. In your propos=
ed syntax, they can only use the conceptual equivalent of unique_ptr&lt;T&g=
t;.</div></div></blockquote><div>=C2=A0</div><div>optional_ptr can have del=
eters and support arrays too. I&#39;ve left all that out for now because it=
s not central to the=C2=A0first question of whether=C2=A0this is actually a=
 good pattern and second whether it has a place in the standard library.</d=
iv><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; padding=
-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; =
border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"><div><br>=
Given that this variant solves your problem adequately, and that your use-c=
ase is fairly niche, I&#39;d say to take the 80% solution and move on.<br><=
/div></div></blockquote><div>=C2=A0</div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_790_452308375.1443118891015--
------=_Part_789_1836315049.1443118891014--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Thu, 24 Sep 2015 11:32:36 -0700 (PDT)
Raw View
------=_Part_451_288863931.1443119556986
Content-Type: multipart/alternative;
 boundary="----=_Part_452_606596372.1443119556986"

------=_Part_452_606596372.1443119556986
Content-Type: text/plain; charset=UTF-8


On Thursday, September 24, 2015 at 1:53:47 PM UTC-4, Jeffrey Yasskin wrote:
>
> We have an optional ownership pattern at Google, involving storing an enum
> next to the pointer. It's fairly bad, but it gets the job done.
>

Hi Jeffrey, could you expand on some specific use cases? Why did you feel
the need to invent optional ownership? Why were the built in unique and
shared ownership patterns not adequate?



> I suspect an optional-ownership class isn't the most important thing the
> committee could be spending time on, but it's not crazy.
>
> Using unique_ptr deleters for this is clever, which is as much criticism
> as it is praise. Having a deleter that doesn't delete makes uses of
> unique_ptr harder to read, and to some extent is an indication that
> move-only types are too hard to write.
>

optional_ptr has to be a move only type because it might own even though
copying is perfectly valid if it does not own. It feels a bit odd but in
practice it hasn't been a problem for me. If you want to copy that means
what you really want is to copy the pointer and have a view, in which case
you can call .get() when can then be passed on to T* or another
optional_ptr which will not be an owner.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_452_606596372.1443119556986
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Thursday, September 24, 2015 at 1:53:47 PM UTC-4, J=
effrey Yasskin wrote:<blockquote style=3D"margin: 0px 0px 0px 0.8ex; paddin=
g-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px;=
 border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr">We have =
an optional ownership pattern at Google, involving storing an enum next to =
the pointer. It&#39;s fairly bad, but it gets the job done.</div></blockquo=
te><div>=C2=A0</div><div>Hi Jeffrey, could you expand on some specific use =
cases? Why did you feel the need to invent optional ownership? Why were the=
 built in unique and shared ownership patterns not adequate?</div><div>=C2=
=A0</div><div>=C2=A0</div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; p=
adding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width:=
 1px; border-left-style: solid;" class=3D"gmail_quote"><div dir=3D"ltr"> I =
suspect an optional-ownership class isn&#39;t the most important thing the =
committee could be spending time on, but it&#39;s not crazy.<div><br></div>=
<div>Using unique_ptr deleters for this is clever, which is as much critici=
sm as it is praise. Having a deleter that doesn&#39;t delete makes uses of =
unique_ptr harder to read, and to some extent is an indication that move-on=
ly types are too hard to write.</div></div></blockquote><div>=C2=A0</div><d=
iv>optional_ptr has to be a=C2=A0move only type because it might own even t=
hough copying is perfectly=C2=A0valid if it does not own. It feels a bit od=
d but in practice it hasn&#39;t been a problem for me. If you want to copy=
=C2=A0that means what you really want=C2=A0is to copy the pointer and have =
a view, in which case you can call .get() when can then be passed on to T* =
or another optional_ptr which will not be an owner.</div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_452_606596372.1443119556986--
------=_Part_451_288863931.1443119556986--

.


Author: "'Jeffrey Yasskin' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 24 Sep 2015 11:46:30 -0700
Raw View
--001a1141ef3c6d74ff052082a7c2
Content-Type: text/plain; charset=UTF-8

On Thu, Sep 24, 2015 at 11:32 AM, Matthew Fioravante <fmatthew5876@gmail.com
> wrote:

>
> On Thursday, September 24, 2015 at 1:53:47 PM UTC-4, Jeffrey Yasskin wrote:
>>
>> We have an optional ownership pattern at Google, involving storing an
>> enum next to the pointer. It's fairly bad, but it gets the job done.
>>
>
> Hi Jeffrey, could you expand on some specific use cases? Why did you feel
> the need to invent optional ownership? Why were the built in unique and
> shared ownership patterns not adequate?
>

Many uses are in wrappers around other data, for example, a gunzip view on
a string or a filtered view of a table, where the library fundamentally
only needs a view on the data, but in many cases the user doesn't want to
deal with stashing ownership of the data somewhere else. Uses are about
evenly split between ones that want the library to take ownership and ones
that don't.


> I suspect an optional-ownership class isn't the most important thing the
>> committee could be spending time on, but it's not crazy.
>>
>> Using unique_ptr deleters for this is clever, which is as much criticism
>> as it is praise. Having a deleter that doesn't delete makes uses of
>> unique_ptr harder to read, and to some extent is an indication that
>> move-only types are too hard to write.
>>
>
> optional_ptr has to be a move only type because it might own even though
> copying is perfectly valid if it does not own. It feels a bit odd but in
> practice it hasn't been a problem for me. If you want to copy that means
> what you really want is to copy the pointer and have a view, in which case
> you can call .get() when can then be passed on to T* or another
> optional_ptr which will not be an owner.
>

I wasn't questioning that. :) In general, we should be willing to allocate
new names, instead of re-using unique_ptr for every move-only type.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a1141ef3c6d74ff052082a7c2
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, Sep 24, 2015 at 11:32 AM, Matthew Fioravante <span dir=3D"ltr">&lt;<a h=
ref=3D"mailto:fmatthew5876@gmail.com" target=3D"_blank" class=3D"cremed">fm=
atthew5876@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><span class=3D""><br>On Thursday, September 24, 2015 at =
1:53:47 PM UTC-4, Jeffrey Yasskin wrote:<blockquote style=3D"margin:0px 0px=
 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-=
width:1px;border-left-style:solid" class=3D"gmail_quote"><div dir=3D"ltr">W=
e have an optional ownership pattern at Google, involving storing an enum n=
ext to the pointer. It&#39;s fairly bad, but it gets the job done.</div></b=
lockquote><div>=C2=A0</div></span><div>Hi Jeffrey, could you expand on some=
 specific use cases? Why did you feel the need to invent optional ownership=
? Why were the built in unique and shared ownership patterns not adequate?<=
/div></div></blockquote><div><br></div><div>Many uses are in wrappers aroun=
d other data, for example, a gunzip view on a string or a filtered view of =
a table, where the library fundamentally only needs a view on the data, but=
 in many cases the user doesn&#39;t want to deal with stashing ownership of=
 the data somewhere else. Uses are about evenly split between ones that wan=
t the library to take ownership and ones that don&#39;t.</div><div>=C2=A0</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><block=
quote style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:=
rgb(204,204,204);border-left-width:1px;border-left-style:solid" class=3D"gm=
ail_quote"><div dir=3D"ltr"> I suspect an optional-ownership class isn&#39;=
t the most important thing the committee could be spending time on, but it&=
#39;s not crazy.<div><br></div><div>Using unique_ptr deleters for this is c=
lever, which is as much criticism as it is praise. Having a deleter that do=
esn&#39;t delete makes uses of unique_ptr harder to read, and to some exten=
t is an indication that move-only types are too hard to write.</div></div><=
/blockquote><div>=C2=A0</div></span><div>optional_ptr has to be a=C2=A0move=
 only type because it might own even though copying is perfectly=C2=A0valid=
 if it does not own. It feels a bit odd but in practice it hasn&#39;t been =
a problem for me. If you want to copy=C2=A0that means what you really want=
=C2=A0is to copy the pointer and have a view, in which case you can call .g=
et() when can then be passed on to T* or another optional_ptr which will no=
t be an owner.</div></div></blockquote><div>=C2=A0</div></div></div><div cl=
ass=3D"gmail_extra">I wasn&#39;t questioning that. :) In general, we should=
 be willing to allocate new names, instead of re-using unique_ptr for every=
 move-only type.</div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a1141ef3c6d74ff052082a7c2--

.


Author: =?UTF-8?Q?Andrzej_Krzemie=C5=84ski?= <akrzemi1@gmail.com>
Date: Thu, 24 Sep 2015 11:52:01 -0700 (PDT)
Raw View
------=_Part_772_501573375.1443120721449
Content-Type: multipart/alternative;
 boundary="----=_Part_773_72899695.1443120721450"

------=_Part_773_72899695.1443120721450
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable



W dniu czwartek, 24 wrze=C5=9Bnia 2015 18:54:55 UTC+2 u=C5=BCytkownik Andre=
y Semashev=20
napisa=C5=82:
>
> On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante=20
> <fmatth...@gmail.com <javascript:>> wrote:=20
> > For all resources, we have owners who manage the lifetime of the=20
> resource=20
> > and viewers who view the resource. To be correct, all of the viewers=20
> have to=20
> > stop using the pointer before the last owner goes out of scope and=20
> destroys=20
> > the resource.=20
>
> If anything, this sounds fragile and dangerous.=20
>

I found myself a couple of times in need of such functionality. I called my=
=20
version `optional_owner`. For sure, it is inferior to unique_ptr (for=20
exclusive ownership) or a raw reference (for no ownership), provided you=20
can use either. But there are some rare cases of resorce-managing schemes=
=20
where unique_ptr will not do. In these cases people resort to shared_ptr,=
=20
and it works, but incorrectly suggest shared ownership, which does not in=
=20
fact take place.

My use case was this: I have an OO-like interface (base class with virtual=
=20
functions), with 4 implementations, one of which is a singleton. In 3 other=
=20
cases I have a factory function that allocates the implementation on the=20
heap and returns a unique_ptr. In the 4th (singleton) case I return a=20
reference to the single object. My colleagues always solve these problems=
=20
by turning everything into shared_ptr (as though it was an ultimate garbage=
=20
collection solution to every management problem). I would prefer they used=
=20
optional_owner instead. Not everywhere: only in specific, rare, complicated=
=20
memory management situations.

Regards,
&rzej  =20

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_773_72899695.1443120721450
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>W dniu czwartek, 24 wrze=C5=9Bnia 2015 18:54:55 UT=
C+2 u=C5=BCytkownik Andrey Semashev napisa=C5=82:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;">On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante
<br>&lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
uwb7kxd9CAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&=
#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true=
;">fmatth...@gmail.com</a>&gt; wrote:
<br>&gt; For all resources, we have owners who manage the lifetime of the r=
esource
<br>&gt; and viewers who view the resource. To be correct, all of the viewe=
rs have to
<br>&gt; stop using the pointer before the last owner goes out of scope and=
 destroys
<br>&gt; the resource.
<br>
<br>If anything, this sounds fragile and dangerous.
<br></blockquote><div><br>I found myself a couple of times in need of such =
functionality. I called my version `optional_owner`. For sure, it is inferi=
or to unique_ptr (for exclusive ownership) or a raw reference (for no owner=
ship), provided you can use either. But there are some rare cases of resorc=
e-managing schemes where unique_ptr will not do. In these cases people reso=
rt to shared_ptr, and it works, but incorrectly suggest shared ownership, w=
hich does not in fact take place.<br><br>My use case was this: I have an OO=
-like interface (base class with virtual functions), with 4 implementations=
, one of which is a singleton. In 3 other cases I have a factory function t=
hat allocates the implementation on the heap and returns a unique_ptr. In t=
he 4th (singleton) case I return a reference to the single object. My colle=
agues always solve these problems by turning everything into shared_ptr (as=
 though it was an ultimate garbage collection solution to every management =
problem). I would prefer they used optional_owner instead. Not everywhere: =
only in specific, rare, complicated memory management situations.<br><br>Re=
gards,<br>&amp;rzej =C2=A0 <br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_773_72899695.1443120721450--
------=_Part_772_501573375.1443120721449--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Thu, 24 Sep 2015 11:59:58 -0700 (PDT)
Raw View
------=_Part_959_1113074978.1443121198409
Content-Type: multipart/alternative;
 boundary="----=_Part_960_1674979995.1443121198409"

------=_Part_960_1674979995.1443121198409
Content-Type: text/plain; charset=UTF-8

Nicol, I can provide another general use case, again related to building
pipelines.

Lets imagine we have data streams. In my example, each data stream will an
object represented by a letter.

For example, we have can a stream A, and another stream B(A) which takes A,
performs some transformations, and then produces new stream B. B accesses A
by storing a pointer to A.

A common case is one producer and many consumers.

A
B(A)
C(A)
D(A)

In this case, A can be owned externally (via unique_ptr or directly on the
stack/data member) and B, C, and D get a view to it.

However we can also have this scenario.

D(C(B(A))).

Here, maybe I'm only interested in the output of D, not the intermediate C,
B, and A streams. A, B, and C may even be completely hidden via a factory
function that creates D. In this case, the most natural thing is to just
let them tag along with D and let D own them. Since D is the only consumer,
once D goes away C, B, and A can all be destroyed. I don't have to manage
any external object to maintain the unique_ptr's that own A, B, and C.

Of course this can all be solved by shared_ptr, but for reasons mentioned
earlier that has a lot of drawbacks. In my mind shared_ptr is only really
needed when you cannot build a heirarchical scoped architecture to manage
the lifetime invariants for you. I try to avoid it unless absolutely
necessary.

Essentially using unique_ptr/T* means that you always have to have an
external manager object to take ownership of the lifetimes. If you want to
construct an producer and consumer in isolation you also need a third
object to hold the unique_ptr object. With optional_ptr, the consumer can
just take the producer if needed.



On Thursday, September 24, 2015 at 2:46:51 PM UTC-4, Jeffrey Yasskin wrote:
>
> On Thu, Sep 24, 2015 at 11:32 AM, Matthew Fioravante <
> *fmatth...@gmail.com* <javascript:>> wrote:
>
>>
>> On Thursday, September 24, 2015 at 1:53:47 PM UTC-4, Jeffrey Yasskin
>> wrote:
>>>
>>> We have an optional ownership pattern at Google, involving storing an
>>> enum next to the pointer. It's fairly bad, but it gets the job done.
>>>
>> Hi Jeffrey, could you expand on some specific use cases? Why did you feel
>> the need to invent optional ownership? Why were the built in unique and
>> shared ownership patterns not adequate?
>>
>
> Many uses are in wrappers around other data, for example, a gunzip view on
> a string or a filtered view of a table, where the library fundamentally
> only needs a view on the data, but in many cases the user doesn't want to
> deal with stashing ownership of the data somewhere else. Uses are about
> evenly split between ones that want the library to take ownership and ones
> that don't.
>

That sounds pretty similar to my use case, another pipeline.







--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_960_1674979995.1443121198409
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Nicol, I can provide another general use case, again =
related to building pipelines.</div><div>=C2=A0</div><div>Lets imagine we h=
ave data streams. In my example, each data stream will an object represente=
d by a letter.</div><div>=C2=A0</div><div>For example, we have can a stream=
 A, and another stream B(A) which takes A, performs some transformations, a=
nd then produces=C2=A0new stream B. B accesses A by=C2=A0storing a pointer =
to A.</div><div>=C2=A0</div><div>A common case is one producer and many con=
sumers.</div><div>=C2=A0</div><div>A</div><div>B(A)</div><div>C(A)</div><di=
v>D(A)</div><div>=C2=A0</div><div>In this case, A can be owned externally (=
via unique_ptr or directly on the stack/data member) and B, C, and D get a =
view to it.</div><div>=C2=A0</div><div>However we can also have this scenar=
io.</div><div>=C2=A0</div><div>D(C(B(A))).</div><div>=C2=A0</div><div>Here,=
 maybe I&#39;m only interested in the output of D, not the intermediate C, =
B, and A streams. A, B, and C may even be completely hidden via a factory f=
unction that creates D. In this case, the most natural thing is to just let=
 them tag along with D and let D own them. Since D is the only consumer, on=
ce D goes away C, B, and A can all be destroyed. I don&#39;t have to manage=
 any external object to maintain the unique_ptr&#39;s that own A, B, and C.=
</div><div>=C2=A0</div><div>Of course this can all be solved by shared_ptr,=
 but for reasons mentioned earlier that has a lot of drawbacks. In my mind =
shared_ptr is only really needed when you cannot build a heirarchical scope=
d architecture to manage the lifetime invariants=C2=A0for you. I try to avo=
id it unless absolutely necessary.</div><div>=C2=A0</div><div>Essentially u=
sing unique_ptr/T* means that you always have to have an external manager o=
bject to take ownership of the lifetimes. If you want to construct an produ=
cer and consumer in isolation you also need a third object to hold the uniq=
ue_ptr object. With optional_ptr, the consumer can just take the producer i=
f needed.</div><div>=C2=A0</div><div>=C2=A0</div><div><br>On Thursday, Sept=
ember 24, 2015 at 2:46:51 PM UTC-4, Jeffrey Yasskin wrote:<blockquote style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;" class=3D"g=
mail_quote"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Sep 24=
, 2015 at 11:32 AM, Matthew Fioravante <span dir=3D"ltr">&lt;<a onmousedown=
=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D=
&#39;javascript:&#39;;return true;" href=3D"javascript:" rel=3D"nofollow" t=
arget=3D"_blank" gdf-obfuscated-mailto=3D"YINbaDODCAAJ"><u><font color=3D"#=
000080">fmatth...@gmail.com</font></u></a>&gt;</span> wrote:<br><blockquote=
 style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: =
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;" clas=
s=3D"gmail_quote"><div dir=3D"ltr"><span><br>On Thursday, September 24, 201=
5 at 1:53:47 PM UTC-4, Jeffrey Yasskin wrote:<blockquote style=3D"margin: 0=
px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204);=
 border-left-width: 1px; border-left-style: solid;" class=3D"gmail_quote"><=
div dir=3D"ltr">We have an optional ownership pattern at Google, involving =
storing an enum next to the pointer. It&#39;s fairly bad, but it gets the j=
ob done.</div></blockquote><div> </div></span><div>Hi Jeffrey, could you ex=
pand on some specific use cases? Why did you feel the need to invent option=
al ownership? Why were the built in unique and shared ownership patterns no=
t adequate?</div></div></blockquote><div><br></div><div>Many uses are in wr=
appers around other data, for example, a gunzip view on a string or a filte=
red view of a table, where the library fundamentally only needs a view on t=
he data, but in many cases the user doesn&#39;t want to deal with stashing =
ownership of the data somewhere else. Uses are about evenly split between o=
nes that want the library to take ownership and ones that don&#39;t.</div><=
/div></div></div></blockquote></div><div>=C2=A0</div><div>That sounds prett=
y similar to my use case, another pipeline.</div><div>=C2=A0</div><div>=C2=
=A0</div><div>=C2=A0</div><div>=C2=A0</div><div>=C2=A0</div><div>=C2=A0</di=
v></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_960_1674979995.1443121198409--
------=_Part_959_1113074978.1443121198409--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 24 Sep 2015 12:38:56 -0700 (PDT)
Raw View
------=_Part_1010_1230412804.1443123536314
Content-Type: multipart/alternative;
 boundary="----=_Part_1011_1112560883.1443123536315"

------=_Part_1011_1112560883.1443123536315
Content-Type: text/plain; charset=UTF-8

On Thursday, September 24, 2015 at 2:21:31 PM UTC-4, Matthew Fioravante
wrote:
>
>
> On Thursday, September 24, 2015 at 12:54:55 PM UTC-4, Andrey Semashev
> wrote:
>>
>> On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante
>> <*fmatth...@gmail.com*> wrote:
>> > For all resources, we have owners who manage the lifetime of the
>> resource
>> > and viewers who view the resource. To be correct, all of the viewers
>> have to
>> > stop using the pointer before the last owner goes out of scope and
>> destroys
>> > the resource.
>>
>> If anything, this sounds fragile and dangerous.
>
>
> This was my concern as well and what I anticipate to be the biggest
> argument against this idiom. However I'm not yet entirely convinced that
> its any less dangerous to the situation where you have a unique_ptr owned
> by A and viewed by B as a T*. Its up to the programmer to ensure that B's
> lifetime is within A's lifetime.
>
> If someone can identify a situation where optional_ptr is much more
> dangerous than unique_ptr/T* that would be really helpful.
>
>
>
>>
>> But, in case you can easily guarantee that the owner outlives the
>> viewers, did you consider using unique_ptr with a custom deleter?
>
>
>  I'm not sure how a custom deleter would help. If the deleter does
> nothing, then you just have T*, if the deleter conditionally deletes the
> object based on a boolean state, you have my optional_ptr. A reusable
> common pattern should have a name, not be a backwards hack on a unique_ptr
> deleter.
>
>
>
> On Thursday, September 24, 2015 at 1:36:37 PM UTC-4, Nicol Bolas wrote:
>>
>>
>>
>> On Thursday, September 24, 2015 at 12:35:28 PM UTC-4, Matthew Fioravante
>> wrote:
>>>
>>> For all resources, we have owners who manage the lifetime of the
>>> resource and viewers who view the resource. To be correct, all of the
>>> viewers have to stop using the pointer before the last owner goes out of
>>> scope and destroys the resource.
>>>
>>> For both unique_ptr and shared_ptr, the set of owners and viewers has to
>>> be decided explicitly ahead of time. This can very limiting because I've
>>> run into cases where I have types which 99% of the time are viewers
>>> (because the resource is often shared) but in some rare contexts need to be
>>> an owner because the object is being used standalone with no external
>>> entity to manage the ownership.
>>>
>>
>> ... This seems to be a problem with how you're thinking of types and
>> ownerships.
>>
>> Types do not define ownership. Or at least, not in the way you seem to
>> mean. What defines ownership is *code*, at compile time.
>>
>
> Not sure I agree, unless I'm misunderstanding you somehow. If a type
> stores an object by unique_ptr or shared_ptr, that type defines ownership
> of the resource. If the type stores by T*, he defines non-ownership.
>

What I mean is that code *chooses* the ownership method. You pick which
type to use based on what ownership that code specifically needs.

Or more to the point, you don't use `unique_ptr` because it provides unique
ownership. You use `unique_ptr` because a particular piece of code needs to
uniquely own an object that's heap-allocated. The code defines the need for
ownership; the type is simply how you implement the ownership model.

Code is static, while your maybe_owns pointer is dynamic. It's not clear to
me what kind of code requires an ownership model that is dynamic.



>
>
>
>
>
>> Because again, you just pass it a T*. If the caller has a `unique_ptr`,
>> and is finished with that `unique_ptr` immediately after calling
>> `do_something2`, they can simply destroy it right after the call.
>>
>> So this is only meaningful if you have an *object* which may or may not
>> own some other object it is given. Can you give a more concrete example of
>> an object that cannot statically know if expects to be given ownership of
>> an object?
>>
>
> Sure, one real example I have is a pipeline. lets say we have
> pipeline that manages 3 data streams A, B, and C with a configurable number
> of stages. Each stage can apply some transformation to A, B, or C or just
> pass it along. When a stage needs to modify a stream, he gets a view of the
> previous stream, allocates and takes ownership of a new one, and then
> applies his transformations to convert A -> A`. If he does not need to
> modify a stream, he just passes along a view of it.
>

Allow me to restate this, so that we can make sure I'm correctly
understanding what you've described in C++ terms.

You have these stage constructs. They're pass 3 objects and return three
objects to the next stage in the sequence. They may modify or not modify
those objects as they see fit as part of their processing.

Your implementation of this concept is that the 3 objects, the data
streams, are *immutable*. Stages don't actually modify them; they create a
modified copy of them. And therefore, a stage may have heap-allocated one
of streams, or it may simply pass the object from the previous stage
through.

It's not clear to me why `unique_ptr` doesn't work here. Maybe I'm missing
something here.

To me, each stage is effectively a function of this form:

void stage(unique_ptr<A> streamA, unique_ptr<B> streamB, unique_ptr<C>
streamC);

By taking `unique_ptr` as a value, that ensures that each stage owns the
object for the duration of that function call. When one stage calls the
next, it passes them pointers. The previous stage therefore transfers
ownership to the next.

If a stage needs to create a modified copy, they simply do this:

unique_ptr<A> oldValue = std::move(streamA);
streamA = make_unique(...);

Or they create the new stream's `unique_ptr` as a local variable and
explicitly move it into the next stream.

Each stage owns the objects it gets, but only for the duration of its
function call. I don't see why stages need to pass optional ownership.

This pattern can be accomplished using shared_ptr but again its unecessary.
> It can also be accomplished with unique_ptr but then each stage has to make
> a copy of each stream and copy the data even if he does not modify it.
>

How does using `unique_ptr` require copying of the data? It's just passing
ownership of an object through to the next stage. Once a stream is passed
to the next stage, the previous stage has no right to access it anymore.

So where is this need to copy each stream coming from? Why does a stage
need to hold onto the objects it was given, instead of transfering
ownership to the next stage?

If a stage needs a modified copy, it can preserve the old object as shown
above. But if it doesn't, then it should just pass ownership to the next
stage. So rather than having each stage store a non-owning pointer that's
owned by a previous stage, each stage stores an owning pointer that is
owned only so long as that stage is processing, or if it's an old copy left
behind.

So I remain confused as to when you would *need* this functionality.


> Every pipeline stage that has a non-owning pointer is guaranteed that the
> pointer is owned by a previous stage. When the stages are destroyed in
> reverse order, all resources are released correctly with epsilon overhead.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1011_1112560883.1443123536315
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thursday, September 24, 2015 at 2:21:31 PM UTC-4, Matthew Fioravante wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>On Thu=
rsday, September 24, 2015 at 12:54:55 PM UTC-4, Andrey Semashev wrote:<bloc=
kquote style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color=
:rgb(204,204,204);border-left-width:1px;border-left-style:solid" class=3D"g=
mail_quote">On Thu, Sep 24, 2015 at 7:35 PM, Matthew Fioravante<br>&lt;<a r=
el=3D"nofollow"><u><font color=3D"#000080">fmatth...@gmail.com</font></u></=
a>&gt; wrote:<br>&gt; For all resources, we have owners who manage the life=
time of the resource<br>&gt; and viewers who view the resource. To be corre=
ct, all of the viewers have to<br>&gt; stop using the pointer before the la=
st owner goes out of scope and destroys<br>&gt; the resource.<br><br>If any=
thing, this sounds fragile and dangerous.</blockquote><div>=C2=A0</div><div=
>This was my concern as well and what I anticipate to be the biggest argume=
nt against this idiom. However I&#39;m not yet entirely convinced that its =
any less dangerous to the situation where you have a unique_ptr=C2=A0owned =
by A and viewed by B as a T*.=C2=A0Its up to the=C2=A0programmer to ensure =
that B&#39;s lifetime is within A&#39;s lifetime.</div><div>=C2=A0</div><di=
v>If someone can identify a situation where optional_ptr is much more dange=
rous than unique_ptr/T* that would be really helpful.</div><div>=C2=A0</div=
><div>=C2=A0</div><blockquote style=3D"margin:0px 0px 0px 0.8ex;padding-lef=
t:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-=
style:solid" class=3D"gmail_quote"><br>But, in case you can easily guarante=
e that the owner outlives the<br>viewers, did you consider using unique_ptr=
 with a custom deleter?</blockquote><div>=C2=A0</div><div>=C2=A0I&#39;m not=
 sure how a custom deleter would help. If the deleter does nothing, then yo=
u just have T*, if the deleter conditionally deletes the object based on a =
boolean state, you have my optional_ptr. A reusable common pattern should h=
ave a name, not be a backwards hack on a unique_ptr deleter.</div><div>=C2=
=A0</div><div>=C2=A0</div><br>On Thursday, September 24, 2015 at 1:36:37 PM=
 UTC-4, Nicol Bolas wrote:<blockquote style=3D"margin:0px 0px 0px 0.8ex;pad=
ding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bord=
er-left-style:solid" class=3D"gmail_quote"><div dir=3D"ltr"><br><br>On Thur=
sday, September 24, 2015 at 12:35:28 PM UTC-4, Matthew Fioravante wrote:<bl=
ockquote style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-col=
or:rgb(204,204,204);border-left-width:1px;border-left-style:solid" class=3D=
"gmail_quote"><div dir=3D"ltr"><div>For all resources, we have=C2=A0owners =
who manage the lifetime of the resource and viewers who view the resource. =
To be correct, all of the viewers have to stop using the pointer before the=
 last owner goes out of scope and destroys the resource.</div><div>=C2=A0</=
div><div>For both unique_ptr and shared_ptr, the set of owners and viewers =
has to be decided explicitly ahead of time. This can very limiting because =
I&#39;ve run into cases where I have types which 99% of the time are viewer=
s (because the resource is often shared)=C2=A0but in some rare contexts nee=
d to be an owner because the object is being used standalone with no extern=
al entity to manage the ownership.</div></div></blockquote><div><br>... Thi=
s seems to be a problem with how you&#39;re thinking of types and ownership=
s.<br><br>Types do not define ownership. Or at least, not in the way you se=
em to mean. What defines ownership is <i>code</i>, at compile time.</div></=
div></blockquote><div>=C2=A0</div><div>Not sure I agree, unless I&#39;m mis=
understanding you somehow. If a type stores an object by unique_ptr or shar=
ed_ptr, that type defines ownership of the resource. If=C2=A0the=C2=A0type =
stores by T*, he defines non-ownership.=C2=A0</div></div></blockquote><div>=
<br>What I mean is that code <i>chooses</i> the ownership method. You pick =
which type to use based on what ownership that code specifically needs.<br>=
<br>Or more to the point, you don&#39;t use `unique_ptr` because it provide=
s unique ownership. You use `unique_ptr` because a particular piece of code=
 needs to uniquely own an object that&#39;s heap-allocated. The code define=
s the need for ownership; the type is simply how you implement the ownershi=
p model.<br><br>Code is static, while your maybe_owns pointer is dynamic. I=
t&#39;s not clear to me what kind of code requires an ownership model that =
is dynamic.<br><br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>=C2=A0</div><div>=C2=A0</div><br><div>=C2=A0</div><b=
lockquote style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-co=
lor:rgb(204,204,204);border-left-width:1px;border-left-style:solid" class=
=3D"gmail_quote"><div dir=3D"ltr"><div>Because again, you just pass it a T*=
.. If the caller has a `unique_ptr`, and is finished with that `unique_ptr` =
immediately after calling `do_something2`, they can simply destroy it right=
 after the call.<br><br>So this is only meaningful if you have an <i>object=
</i> which may or may not own some other object it is given. Can you give a=
 more concrete example of an object that cannot statically know if expects =
to be given ownership of an object?</div></div></blockquote><div>=C2=A0</di=
v><div>Sure, one=C2=A0real example I have is a pipeline. lets say we have p=
ipeline=C2=A0that manages=C2=A03 data streams A, B, and C with a configurab=
le number of stages. Each stage can=C2=A0apply some transformation to=C2=A0=
A, B, or C or just pass it along. When a stage needs to modify a stream, he=
 gets a view of the previous stream, allocates and takes ownership of a new=
 one, and then applies his transformations to convert A -&gt; A`. If he doe=
s not need to modify a stream, he just passes along a view of it.</div></di=
v></blockquote><div><br>Allow me to restate this, so that we can make sure =
I&#39;m correctly understanding what you&#39;ve described in C++ terms.<br>=
<br>You have these stage constructs. They&#39;re pass 3 objects and return =
three objects to the next stage in the sequence. They may modify or not mod=
ify those objects as they see fit as part of their processing.<br><br>Your =
implementation of this concept is that the 3 objects, the data streams, are=
 <i>immutable</i>. Stages don&#39;t actually modify them; they create a mod=
ified copy of them. And therefore, a stage may have heap-allocated one of s=
treams, or it may simply pass the object from the previous stage through.<b=
r><br>It&#39;s not clear to me why `unique_ptr` doesn&#39;t work here. Mayb=
e I&#39;m missing something here.<br><br>To me, each stage is effectively a=
 function of this form:<br><br><div class=3D"prettyprint" style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> stage</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">A</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> streamA</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> unique_ptr</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">B</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> streamB</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> unique_ptr</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">C</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> stre=
amC</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n></div></code></div><br>By taking `unique_ptr` as a value, that ensures th=
at each stage owns the object for the duration of that function call. When =
one stage calls the next, it passes them pointers. The previous stage there=
fore transfers ownership to the next.<br><br>If a stage needs to create a m=
odified copy, they simply do this:<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 clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;=
" class=3D"styled-by-prettify">unique_ptr</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">A</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> oldValue </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> 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 sty=
le=3D"color: #000;" class=3D"styled-by-prettify">streamA</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>streamA </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> make_unique</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(...);</span></div></code></div><br>Or =
they create the new stream&#39;s `unique_ptr` as a local variable and expli=
citly move it into the next stream.<br><br>Each stage owns the objects it g=
ets, but only for the duration of its function call. I don&#39;t see why st=
ages need to pass optional ownership.<br><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>This pattern can be a=
ccomplished using shared_ptr but again its unecessary. It can also be accom=
plished with unique_ptr but then each stage has to make a copy of each stre=
am and copy the data even if he does not modify it.</div></div></blockquote=
><div><br>How does using `unique_ptr` require copying of the data? It&#39;s=
 just passing ownership of an object through to the next stage. Once a stre=
am is passed to the next stage, the previous stage has no right to access i=
t anymore.<br><br>So where is this need to copy each stream coming from? Wh=
y does a stage need to hold onto the objects it was given, instead of trans=
fering ownership to the next stage?<br><br>If a stage needs a modified copy=
, it can preserve the old object as shown above. But if it doesn&#39;t, the=
n it should just pass ownership to the next stage. So rather than having ea=
ch stage store a non-owning pointer that&#39;s owned by a previous stage, e=
ach stage stores an owning pointer that is owned only so long as that stage=
 is processing, or if it&#39;s an old copy left behind.<br><br>So I remain =
confused as to when you would <i>need</i> this functionality.<br>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Every =
pipeline stage that has a non-owning pointer is guaranteed that the pointer=
 is owned by a previous stage. When the stages are destroyed in reverse ord=
er, all resources are released correctly with epsilon overhead.<br></div></=
div></blockquote>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1011_1112560883.1443123536315--
------=_Part_1010_1230412804.1443123536314--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Thu, 24 Sep 2015 13:12:32 -0700 (PDT)
Raw View
------=_Part_607_1797949445.1443125553033
Content-Type: multipart/alternative;
 boundary="----=_Part_608_802110742.1443125553034"

------=_Part_608_802110742.1443125553034
Content-Type: text/plain; charset=UTF-8


On Thursday, September 24, 2015 at 3:38:56 PM UTC-4, Nicol Bolas wrote:
>
>
> So I remain confused as to when you would *need* this functionality.


Hi Nicol, sorry if my example was confusing. The A, B, and C objects are
streams, not individual peices of data. Its not a chain of function calls
but instead an object graph which we initialize once and then stream data
through.

First we setup our pipeline stages (think of it like a graph) and then we
start streaming data through it one element at a time. The one time setup
phase is where need to manage lifetimes and where optional_ptr comes into
play.

Here is one example:

      | 0  | 1  | 2  | 3  |
A0 -> | A0 | A0 | A1 | A1 | ->
B0 -> | B0 | B0 | B0 | B1 | ->
C0 -> | C1 | C2 | C3 | C4 | ->


In this example, stage 0 and 1 only work on stream C, stage 2 on A and C,
and stage 3 B and C.
This means that 0 owns C1, 1 owns C2,  2 owns A1 and C3, and finally 3 owns
B1 and C4.

A0, B0, C0 are raw pointers coming from outside and are owned by someone
else, possibly another pipeline. The point is we don't care because we just
pass pointers to streams in and get pointers to streams back out.

The code would look something like this (pardon the ugliness and terseness
but hopefully it makes the point):
using s = stream;

struct stage {
stage(s* ain, s* bin, s* cin, optional_ptr<s> aout, optional_ptr<s> bout,
optional_ptr<s> cout)
 : inputs{ain, bin, cin}, outputs{std::move(aout), std::move(bout), std::
move(cout)} {}

s* inputs[3];
optional_ptr<s> outputs[3];
virtual void process_next() = 0;
};

struct stage0 : public stage {
  stage0(s* a, s* b, s* c)
   : stage(a, b, c, a, b, std::make_unique<stream>()) {}
  void process_next() {
    outputs[2].push_back(transform(inputs[2].back()));
  }
};



--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_608_802110742.1443125553034
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Thursday, September 24, 2015 at 3:38:56 PM UTC-4, N=
icol Bolas wrote:<blockquote style=3D"margin: 0px 0px 0px 0.8ex; padding-le=
ft: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; bor=
der-left-style: solid;" class=3D"gmail_quote"><br>So I remain confused as t=
o when you would <i>need</i> this functionality.</blockquote><div>=C2=A0</d=
iv><div>Hi Nicol, sorry if my example was confusing. The A, B, and C object=
s are streams, not individual peices of data. Its not a chain of function c=
alls but instead an object graph which we=C2=A0initialize once and then=C2=
=A0stream data through.</div><div>=C2=A0</div><div>First we setup our pipel=
ine stages=C2=A0(think of it like a graph) and then we start streaming data=
 through it one element at a time. The one time setup phase is where need t=
o manage lifetimes and where optional_ptr comes into play.</div><div>=C2=A0=
</div><div>Here is one example:</div><div>=C2=A0</div><div style=3D"border:=
 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb=
(250, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><font color=3D"#666600"><span style=3D"color: rgb(0,=
 0, 0);" class=3D"styled-by-prettify">=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">0</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =C2=A0</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">1<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
=C2=A0</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-=
prettify">2</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"> =C2=A0</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"=
styled-by-prettify">3</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> =C2=A0</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"><br>A0 </span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">-&gt;</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">|</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify"> A0 </span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A0 </span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A1 </span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A1 </span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">-&gt;</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <br>B=
0 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">-&gt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-=
prettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-p=
rettify"> B0 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> B0 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> B0 </span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> B1 </span><span style=3D"color: rgb(102, 102, 0);"=
 class=3D"styled-by-prettify">|</span><span style=3D"color: rgb(0, 0, 0);" =
class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"color: rgb(0, 0,=
 0);" class=3D"styled-by-prettify"><br>C0 </span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">-&gt;</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span style=3D"co=
lor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> C1 </span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> C2 </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> C3 </span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> C4 </span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">|</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">-&=
gt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
><br></span></font></div></code></div><p>=C2=A0</p><div>In this example, st=
age 0 and 1=C2=A0only work on stream C, stage 2 on A and C, and stage 3 B a=
nd C.</div><div>This means that 0 owns C1, 1 owns C2,=C2=A0 2 owns A1 and C=
3, and finally 3 owns B1 and C4.</div><div>=C2=A0</div><div>A0, B0, C0 are =
raw pointers coming from outside and are owned by someone else, possibly an=
other pipeline. The point is we don&#39;t care because we just pass pointer=
s to streams in and get pointers to streams back out.</div><div>=C2=A0</div=
><div>The code would look something like this (pardon the ugliness and ters=
eness but hopefully it makes the point):</div><div><div style=3D"border: 1p=
x solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(25=
0, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-=
by-prettify">using</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"> s </span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> stream</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0,=
 0, 136);" class=3D"styled-by-prettify">struct</span><span style=3D"color: =
rgb(0, 0, 0);" class=3D"styled-by-prettify"> stage </span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><font color=
=3D"#000000"><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy">stage</span></font><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify">s</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> ain</span><span style=3D"color: rgb(102, 102, 0);" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> s</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">*</span><span style=3D"color: rgb(0, 0, 0);" cl=
ass=3D"styled-by-prettify"> bin</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> s</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">*</span><span style=3D"color: rgb(0, 0,=
 0);" class=3D"styled-by-prettify"> cin</span><span style=3D"color: rgb(102=
, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"color: rgb(=
0, 0, 0);" class=3D"styled-by-prettify"> optional_ptr</span><span style=3D"=
color: rgb(0, 136, 0);" class=3D"styled-by-prettify">&lt;s&gt;</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> aout</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> optional=
_ptr</span><span style=3D"color: rgb(0, 136, 0);" class=3D"styled-by-pretti=
fy">&lt;s&gt;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"> bout</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"> optional_ptr</span><span style=3D"color: rgb(0, 136, 0);"=
 class=3D"styled-by-prettify">&lt;s&gt;</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> cout</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">)</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">:</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> inputs</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">ain</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> bin</sp=
an><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> ci=
n</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">},</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> outputs</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify">std</span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify">move</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify">aout</span><span style=3D"color: rgb(102, 102, 0);"=
 class=3D"styled-by-prettify">),</span><span style=3D"color: rgb(0, 0, 0);"=
 class=3D"styled-by-prettify"> std</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">::</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify">move</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb=
(0, 0, 0);" class=3D"styled-by-prettify">bout</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">),</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: rgb(102, 102, 0);" class=3D"styled-by-prettify">::</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">move</span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">cout</span><spa=
n style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)}</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{}</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><b=
r>s</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prett=
ify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pretti=
fy"> inputs</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">[</span><span style=3D"color: rgb(0, 102, 102);" class=3D"styl=
ed-by-prettify">3</span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify">];</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"><br>optional_ptr</span><span style=3D"color: rgb(0, 136,=
 0);" class=3D"styled-by-prettify">&lt;s&gt;</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"> outputs</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">[</span><span style=3D"=
color: rgb(0, 102, 102);" class=3D"styled-by-prettify">3</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">];</span><span s=
tyle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span=
 style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">virtual</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span=
><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">void</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> pro=
cess_next</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">()</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: rgb(0, 0, 0);" class=3D"style=
d-by-prettify"> </span><span style=3D"color: rgb(0, 102, 102);" class=3D"st=
yled-by-prettify">0</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">;</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: rgb(102, 102, 0);" cla=
ss=3D"styled-by-prettify">};</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 13=
6);" class=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0,=
 0, 0);" class=3D"styled-by-prettify"> stage0 </span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">:</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color=
: rgb(0, 0, 136);" class=3D"styled-by-prettify">public</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> stage </span><span sty=
le=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0 stag=
e0</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y">s</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pret=
tify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prett=
ify"> a</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> s</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-b=
y-prettify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by=
-prettify"> b</span><span style=3D"color: rgb(102, 102, 0);" class=3D"style=
d-by-prettify">,</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled=
-by-prettify"> s</span><span style=3D"color: rgb(102, 102, 0);" class=3D"st=
yled-by-prettify">*</span><span style=3D"color: rgb(0, 0, 0);" class=3D"sty=
led-by-prettify"> c</span><span style=3D"color: rgb(102, 102, 0);" class=3D=
"styled-by-prettify">)</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">:</span><span style=3D"color: rgb(0,=
 0, 0);" class=3D"styled-by-prettify"> stage</span><span style=3D"color: rg=
b(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color:=
 rgb(0, 0, 0);" class=3D"styled-by-prettify">a</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> c</span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> a</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> b</span><span st=
yle=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span=
 style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> std</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">::</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">make_uni=
que</span><span style=3D"color: rgb(0, 136, 0);" class=3D"styled-by-prettif=
y">&lt;stream&gt;</span><span style=3D"color: rgb(102, 102, 0);" class=3D"s=
tyled-by-prettify">())</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">{}</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: rgb(0, 0, 1=
36);" class=3D"styled-by-prettify">void</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"> process_next</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">()</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 ou=
tputs</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pre=
ttify">[</span><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-=
prettify">2</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">].</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-=
by-prettify">push_back</span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify">transform</span><span style=3D"color: rgb(102, 102,=
 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify">inputs</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">[</span><span style=3D"color: rgb=
(0, 102, 102);" class=3D"styled-by-prettify">2</span><span style=3D"color: =
rgb(102, 102, 0);" class=3D"styled-by-prettify">].</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify">back</span><span style=3D"c=
olor: rgb(102, 102, 0);" class=3D"styled-by-prettify">()));</span><span sty=
le=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0 </span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">}</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
};</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
<br></span></div></code></div><br><br><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_608_802110742.1443125553034--
------=_Part_607_1797949445.1443125553033--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Thu, 24 Sep 2015 16:14:20 -0400
Raw View
On 2015-09-24 15:38, Nicol Bolas wrote:
> It's not clear to me what kind of code requires an ownership model
> that is dynamic.

Generic algorithms. The pipeline example, for one. That is, something
that will operate on an object and not leak memory, whether it gets a
view of the object, or ownership of the object. (It's implied that the
pipeline stages are not static, or at least that the ownership model is
not baked into the API.)

> Allow me to restate this, so that we can make sure I'm correctly
> understanding what you've described in C++ terms.
>
> You have these stage constructs. They're pass 3 objects and return three
> objects to the next stage in the sequence. They may modify or not modify
> those objects as they see fit as part of their processing.
>
> Your implementation of this concept is that the 3 objects, the data
> streams, are *immutable*. Stages don't actually modify them; they create a
> modified copy of them. And therefore, a stage may have heap-allocated one
> of streams, or it may simply pass the object from the previous stage
> through.
>
> It's not clear to me why `unique_ptr` doesn't work here. Maybe I'm missing
> something here.

A stage may retain its input for later use. Or the caller of the
pipeline may retain the input for whatever reason, and want to avoid
needing to make a copy. (Maybe the original input came from a source
that can't be coerced into a proper unique_ptr<T>, e.g. because we
loaded the input as U, and can get a view T of the input, but can't take
ownership of the T. This can often happen if T is an array of primitive
type and U is some library-specific container type.)

> How does using `unique_ptr` require copying of the data? It's just passing
> ownership of an object through to the next stage.

....which precludes retaining ownership. Let's say we are talking about a
stepped pipeline (fairly common, e.g. a video processing pipeline).
Let's say that a particular stage's output is dependent on its previous
output. Obviously, then, in the stage's internal state, it needs to
retain a copy of its previous output (at least in some architectures).

With unique_ptr, this means it has to make a copy of the output to pass
to the next stage, since it is required to relinquish ownership. With
optional_ptr, it can just return a non-owning pointer.

--
Matthew

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Thu, 24 Sep 2015 20:52:07 -0700 (PDT)
Raw View
------=_Part_1872_1818562853.1443153127196
Content-Type: multipart/alternative;
 boundary="----=_Part_1873_2090124253.1443153127197"

------=_Part_1873_2090124253.1443153127197
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thursday, September 24, 2015 at 1:14:35 PM UTC-7, Matthew Woehlke wrote:
>
> On 2015-09-24 15:38, Nicol Bolas wrote:=20
> > It's not clear to me what kind of code requires an ownership model=20
> > that is dynamic.=20
>
> Generic algorithms. The pipeline example, for one. That is, something=20
> that will operate on an object and not leak memory, whether it gets a=20
> view of the object, or ownership of the object. (It's implied that the=20
> pipeline stages are not static, or at least that the ownership model is=
=20
> not baked into the API.)=20
>
> > Allow me to restate this, so that we can make sure I'm correctly=20
> > understanding what you've described in C++ terms.=20
> >=20
> > You have these stage constructs. They're pass 3 objects and return thre=
e=20
> > objects to the next stage in the sequence. They may modify or not modif=
y=20
> > those objects as they see fit as part of their processing.=20
> >=20
> > Your implementation of this concept is that the 3 objects, the data=20
> > streams, are *immutable*. Stages don't actually modify them; they creat=
e=20
> a=20
> > modified copy of them. And therefore, a stage may have heap-allocated=
=20
> one=20
> > of streams, or it may simply pass the object from the previous stage=20
> > through.=20
> >=20
> > It's not clear to me why `unique_ptr` doesn't work here. Maybe I'm=20
> missing=20
> > something here.=20
>
> A stage may retain its input for later use. Or the caller of the=20
> pipeline may retain the input for whatever reason, and want to avoid=20
> needing to make a copy. (Maybe the original input came from a source=20
> that can't be coerced into a proper unique_ptr<T>, e.g. because we=20
> loaded the input as U, and can get a view T of the input, but can't take=
=20
> ownership of the T. This can often happen if T is an array of primitive=
=20
> type and U is some library-specific container type.)=20
>
> > How does using `unique_ptr` require copying of the data? It's just=20
> passing=20
> > ownership of an object through to the next stage.=20
>
> ...which precludes retaining ownership. Let's say we are talking about a=
=20
> stepped pipeline (fairly common, e.g. a video processing pipeline).=20
> Let's say that a particular stage's output is dependent on its previous=
=20
> output. Obviously, then, in the stage's internal state, it needs to=20
> retain a copy of its previous output (at least in some architectures).=20
>
> With unique_ptr, this means it has to make a copy of the output to pass=
=20
> to the next stage, since it is required to relinquish ownership. With=20
> optional_ptr, it can just return a non-owning pointer.=20
>

Doesn't this prove absolutely why optional_ptr is a bad idea? Let's say I=
=20
have a pipeline stage

optional_ptr<T> A(optional_ptr<T> input)
{
    static optional_ptr<T> saved =3D nullptr;
    compute_something_with(input, saved);
    saved =3D std::move(input);  // the original input is now owned by me
    return saved.get();  // return a non-owning handle to the original inpu=
t
}

then if I chain together a couple of calls =E2=80=94

    optional_ptr<T> t1 =3D ...;
    optional_ptr<T> t2 =3D A(std::move(t1));
    optional_ptr<T> t3 =3D A(std::move(t2));

t1 was an owning handle, but now it's moved-from.
A took ownership of the t1-pointed object, saved ownership in `saved`, and=
=20
passed back a non-owning handle as t2.
Then the second A takes t2, saves the non-owning handle in `saved`=20
(remember, it can't tell the difference between the owning pointer and a=20
non-owning handle, by design), and returns another non-owning handle.

However, when the second A saved the non-owning handle in `saved`, it=20
clobbered `saved`'s OLD value, which is to say, the owning pointer to the=
=20
original object! So that object's lifetime is now over, but we have these=
=20
non-owning handles still pointing to it. In other words, things are=20
dangling all over the place.

The smart pointer classes are designed specifically to eliminate this whole=
=20
class of mistakes.
There's no sense in trying to wrap a might-be-owning-might-not-be-owning=20
pointer in something that looks like a smart pointer class, because it=20
fundamentally is NOT a smart pointer; it's just a plain old=20
might-be-owning-might-not-be-owning-might-be-dangling raw pointer. IF you=
=20
want one of those, C++ already has them; they're spelled (T*).

=E2=80=93Arthur

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_1873_2090124253.1443153127197
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thursday, September 24, 2015 at 1:14:35 PM UTC-7, Matthew Woehlke wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;">On 2015-09-24 15:38, Nicol Bol=
as wrote:
<br>&gt; It&#39;s not clear to me what kind of code requires an ownership m=
odel
<br>&gt; that is dynamic.
<br>
<br>Generic algorithms. The pipeline example, for one. That is, something
<br>that will operate on an object and not leak memory, whether it gets a
<br>view of the object, or ownership of the object. (It&#39;s implied that =
the
<br>pipeline stages are not static, or at least that the ownership model is
<br>not baked into the API.)
<br>
<br>&gt; Allow me to restate this, so that we can make sure I&#39;m correct=
ly=20
<br>&gt; understanding what you&#39;ve described in C++ terms.
<br>&gt;=20
<br>&gt; You have these stage constructs. They&#39;re pass 3 objects and re=
turn three=20
<br>&gt; objects to the next stage in the sequence. They may modify or not =
modify=20
<br>&gt; those objects as they see fit as part of their processing.
<br>&gt;=20
<br>&gt; Your implementation of this concept is that the 3 objects, the dat=
a=20
<br>&gt; streams, are *immutable*. Stages don&#39;t actually modify them; t=
hey create a=20
<br>&gt; modified copy of them. And therefore, a stage may have heap-alloca=
ted one=20
<br>&gt; of streams, or it may simply pass the object from the previous sta=
ge=20
<br>&gt; through.
<br>&gt;=20
<br>&gt; It&#39;s not clear to me why `unique_ptr` doesn&#39;t work here. M=
aybe I&#39;m missing=20
<br>&gt; something here.
<br>
<br>A stage may retain its input for later use. Or the caller of the
<br>pipeline may retain the input for whatever reason, and want to avoid
<br>needing to make a copy. (Maybe the original input came from a source
<br>that can&#39;t be coerced into a proper unique_ptr&lt;T&gt;, e.g. becau=
se we
<br>loaded the input as U, and can get a view T of the input, but can&#39;t=
 take
<br>ownership of the T. This can often happen if T is an array of primitive
<br>type and U is some library-specific container type.)
<br>
<br>&gt; How does using `unique_ptr` require copying of the data? It&#39;s =
just passing=20
<br>&gt; ownership of an object through to the next stage.
<br>
<br>...which precludes retaining ownership. Let&#39;s say we are talking ab=
out a
<br>stepped pipeline (fairly common, e.g. a video processing pipeline).
<br>Let&#39;s say that a particular stage&#39;s output is dependent on its =
previous
<br>output. Obviously, then, in the stage&#39;s internal state, it needs to
<br>retain a copy of its previous output (at least in some architectures).
<br>
<br>With unique_ptr, this means it has to make a copy of the output to pass
<br>to the next stage, since it is required to relinquish ownership. With
<br>optional_ptr, it can just return a non-owning pointer.
<br></blockquote><div><br></div><div>Doesn&#39;t this prove absolutely why =
optional_ptr is a bad idea? Let&#39;s say I have a pipeline stage</div><div=
><br></div><div>optional_ptr&lt;T&gt; A(optional_ptr&lt;T&gt; input)</div><=
div>{</div><div>=C2=A0 =C2=A0 static optional_ptr&lt;T&gt; saved =3D nullpt=
r;</div><div>=C2=A0 =C2=A0 compute_something_with(input, saved);</div><div>=
=C2=A0 =C2=A0 saved =3D std::move(input); =C2=A0// the original input is no=
w owned by me</div><div>=C2=A0 =C2=A0 return saved.get(); =C2=A0// return a=
 non-owning handle to the original input</div><div>}</div><div><br></div><d=
iv>then if I chain together a couple of calls =E2=80=94</div><div><br></div=
><div>=C2=A0 =C2=A0 optional_ptr&lt;T&gt; t1 =3D ...;</div><div>=C2=A0 =C2=
=A0 optional_ptr&lt;T&gt; t2 =3D A(std::move(t1));</div><div><div>=C2=A0 =
=C2=A0 optional_ptr&lt;T&gt; t3 =3D A(std::move(t2));</div></div><div><br><=
/div><div>t1 was an owning handle, but now it&#39;s moved-from.</div><div>A=
 took ownership of the t1-pointed object, saved ownership in `saved`, and p=
assed back a non-owning handle as t2.</div><div>Then the second A takes t2,=
 saves the non-owning handle in `saved` (remember, it can&#39;t tell the di=
fference between the owning pointer and a non-owning handle, by design), an=
d returns another non-owning handle.</div><div><br></div><div>However, when=
 the second A saved the non-owning handle in `saved`, it clobbered `saved`&=
#39;s OLD value, which is to say, the owning pointer to the original object=
! So that object&#39;s lifetime is now over, but we have these non-owning h=
andles still pointing to it. In other words, things are dangling all over t=
he place.</div><div><br></div><div>The smart pointer classes are designed s=
pecifically to eliminate this whole class of mistakes.</div><div>There&#39;=
s no sense in trying to wrap a might-be-owning-might-not-be-owning pointer =
in something that looks like a smart pointer class, because it fundamentall=
y is NOT a smart pointer; it&#39;s just a plain old might-be-owning-might-n=
ot-be-owning-might-be-dangling raw pointer. IF you want one of those, C++ a=
lready has them; they&#39;re spelled (T*).</div><div><br></div><div>=E2=80=
=93Arthur</div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1873_2090124253.1443153127197--
------=_Part_1872_1818562853.1443153127196--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Thu, 24 Sep 2015 21:29:16 -0700 (PDT)
Raw View
------=_Part_1284_3201277.1443155356250
Content-Type: multipart/alternative;
 boundary="----=_Part_1285_571680889.1443155356252"

------=_Part_1285_571680889.1443155356252
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable



On Thursday, September 24, 2015 at 11:52:07 PM UTC-4, Arthur O'Dwyer wrote:
>
> On Thursday, September 24, 2015 at 1:14:35 PM UTC-7, Matthew Woehlke wrot=
e:
>>
>> On 2015-09-24 15:38, Nicol Bolas wrote:=20
>> > It's not clear to me what kind of code requires an ownership model=20
>> > that is dynamic.=20
>>
>> Generic algorithms. The pipeline example, for one. That is, something=20
>> that will operate on an object and not leak memory, whether it gets a=20
>> view of the object, or ownership of the object. (It's implied that the=
=20
>> pipeline stages are not static, or at least that the ownership model is=
=20
>> not baked into the API.)=20
>>
>> > Allow me to restate this, so that we can make sure I'm correctly=20
>> > understanding what you've described in C++ terms.=20
>> >=20
>> > You have these stage constructs. They're pass 3 objects and return=20
>> three=20
>> > objects to the next stage in the sequence. They may modify or not=20
>> modify=20
>> > those objects as they see fit as part of their processing.=20
>> >=20
>> > Your implementation of this concept is that the 3 objects, the data=20
>> > streams, are *immutable*. Stages don't actually modify them; they=20
>> create a=20
>> > modified copy of them. And therefore, a stage may have heap-allocated=
=20
>> one=20
>> > of streams, or it may simply pass the object from the previous stage=
=20
>> > through.=20
>> >=20
>> > It's not clear to me why `unique_ptr` doesn't work here. Maybe I'm=20
>> missing=20
>> > something here.=20
>>
>> A stage may retain its input for later use. Or the caller of the=20
>> pipeline may retain the input for whatever reason, and want to avoid=20
>> needing to make a copy. (Maybe the original input came from a source=20
>> that can't be coerced into a proper unique_ptr<T>, e.g. because we=20
>> loaded the input as U, and can get a view T of the input, but can't take=
=20
>> ownership of the T. This can often happen if T is an array of primitive=
=20
>> type and U is some library-specific container type.)=20
>>
>> > How does using `unique_ptr` require copying of the data? It's just=20
>> passing=20
>> > ownership of an object through to the next stage.=20
>>
>> ...which precludes retaining ownership. Let's say we are talking about a=
=20
>> stepped pipeline (fairly common, e.g. a video processing pipeline).=20
>> Let's say that a particular stage's output is dependent on its previous=
=20
>> output. Obviously, then, in the stage's internal state, it needs to=20
>> retain a copy of its previous output (at least in some architectures).=
=20
>>
>> With unique_ptr, this means it has to make a copy of the output to pass=
=20
>> to the next stage, since it is required to relinquish ownership. With=20
>> optional_ptr, it can just return a non-owning pointer.=20
>>
>
> Doesn't this prove absolutely why optional_ptr is a bad idea? Let's say I=
=20
> have a pipeline stage
>
> optional_ptr<T> A(optional_ptr<T> input)
> {
>     static optional_ptr<T> saved =3D nullptr;
>     compute_something_with(input, saved);
>     saved =3D std::move(input);  // the original input is now owned by me
>     return saved.get();  // return a non-owning handle to the original=20
> input
> }
>
> then if I chain together a couple of calls =E2=80=94
>
>     optional_ptr<T> t1 =3D ...;
>     optional_ptr<T> t2 =3D A(std::move(t1));
>     optional_ptr<T> t3 =3D A(std::move(t2));
>
> t1 was an owning handle, but now it's moved-from.
> A took ownership of the t1-pointed object, saved ownership in `saved`, an=
d=20
> passed back a non-owning handle as t2.
> Then the second A takes t2, saves the non-owning handle in `saved`=20
> (remember, it can't tell the difference between the owning pointer and a=
=20
> non-owning handle, by design), and returns another non-owning handle.
>
> However, when the second A saved the non-owning handle in `saved`, it=20
> clobbered `saved`'s OLD value, which is to say, the owning pointer to the=
=20
> original object! So that object's lifetime is now over, but we have these=
=20
> non-owning handles still pointing to it. In other words, things are=20
> dangling all over the place.
>
> The smart pointer classes are designed specifically to eliminate this=20
> whole class of mistakes.
> There's no sense in trying to wrap a might-be-owning-might-not-be-owning=
=20
> pointer in something that looks like a smart pointer class, because it=20
> fundamentally is NOT a smart pointer; it's just a plain old=20
> might-be-owning-might-not-be-owning-might-be-dangling raw pointer. IF you=
=20
> want one of those, C++ already has them; they're spelled (T*).
>

I'm not sure where you guys are getting these insane designs. That code=20
doesn't even make sense. optional_ptr is not meant to be passed around=20
willy nilly. Its meant to be used as a sink. In general you may be passing=
=20
an optional_ptr to a function for final storage, but rarely if ever=20
returning it.

In my design, each stage receives a non-owning view to the input and owns=
=20
his output. The external world only deals in T*. A T* is passed in for the=
=20
input, and a T* is exposed as the output. The clients of the interface are=
=20
completely unburdened with memory management concerns.

Lets try this one more time. We start with unique_ptr and a single stream:

class stage {
public:=20
 stage(T* input) : _input(input), _output(std::make_unique<T>()) {}
 T* input() { return _input; }
 T* output() { return _output.get(); }

 virtual void process_next() =3D 0;
private:
 T* _input;
 unique_ptr<T> _output;
};

Now suppose I want to have a stage which just passes through the input=20
without doing anything. Using unique_ptr, that means I need to allocate a=
=20
new output stream and copy the data.

class noop_stage : public stage {
 virtual void process_next() {
 _output()->push_back(input()->back());
 }
};

This of course is pointless and wastes memory and cpu time. So instead lets=
=20
use optional pointer and now the noop_stage can just passthrough his input=
=20
and not do any computation at all.

class stage {
protected:=20
 stage(T* input, optional_ptr<T> output) : _input(input), _output(std::move=
(
output)) {}
public:
 T* input() { return _input; }
 T* output() { return _output.get(); }

 virtual void process_next() =3D 0;
private:
 T* _input;
 optional_ptr<T> _output;
};

class noop_stage : public stage {
public:
 noop_stage(T* input) : stage(input, input) {}
 virtual void process_next() { /* do nothing! */ }
};

class real_stage : public stage {
public:
 real_stage(T* input) : stage(input, std::make_unique<T>()) {}
 virtual void process_next() { output()->push_back(transform(input()->back
())); }
};

With optional_ptr, we don't need to pollute our interface with shared_ptr.=
=20
Clients are none the wiser and can safely deal with T* pointers whose=20
lifetimes are managed. This of course assumes the client manages the=20
lifetimes of the pipeline stages correctly, but of course in any sane=20
system that part will also be handled by a higher level pipeline class=20
which correctly manages the stages and continues to shield clients from the=
=20
possibility of memory management bugs.

class pipeline {
public:
 pipeline(T* input) : _input(input);

 T* input() { return _input; }
 T* output() { return _stages.empty() ? input() : _stages.back().output(); =
}

 template <typename S, typename... Args>
 void append_stage<S>(Args&&... args) {
  _stages.push_back(std::make_unique<S>(output(), std::forward<Args>(args
)...);
 }

 void process_next() {
   for(auto& s: _stages) {
     s->process_next();
   }
 }

private:
 T* _input;
 std::vector<std::unique_ptr<stage>> _stages;
};

Of course for a single stream design like this, a noop_stage has little=20
value outside of debugging and it doesn't make much sense to alter the=20
design to accomodate optimizing it. For a pipeline with multiple inputs and=
=20
outputs, where its common for many of them to not be transformed by every=
=20
stage, being able to passthrough the inputs as outputs is critical to=20
performance. I'll leave extending this code snippet for multiple inputs and=
=20
outputs as an exercise for the reader.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_1285_571680889.1443155356252
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<br><br>On Thursday, September 24, 2015 at 11:52:07 PM UTC-4, Arthur O&#39;=
Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thursday, Septe=
mber 24, 2015 at 1:14:35 PM UTC-7, Matthew Woehlke wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex">On 2015-09-24 15:38, Nicol Bolas wrote:
<br>&gt; It&#39;s not clear to me what kind of code requires an ownership m=
odel
<br>&gt; that is dynamic.
<br>
<br>Generic algorithms. The pipeline example, for one. That is, something
<br>that will operate on an object and not leak memory, whether it gets a
<br>view of the object, or ownership of the object. (It&#39;s implied that =
the
<br>pipeline stages are not static, or at least that the ownership model is
<br>not baked into the API.)
<br>
<br>&gt; Allow me to restate this, so that we can make sure I&#39;m correct=
ly=20
<br>&gt; understanding what you&#39;ve described in C++ terms.
<br>&gt;=20
<br>&gt; You have these stage constructs. They&#39;re pass 3 objects and re=
turn three=20
<br>&gt; objects to the next stage in the sequence. They may modify or not =
modify=20
<br>&gt; those objects as they see fit as part of their processing.
<br>&gt;=20
<br>&gt; Your implementation of this concept is that the 3 objects, the dat=
a=20
<br>&gt; streams, are *immutable*. Stages don&#39;t actually modify them; t=
hey create a=20
<br>&gt; modified copy of them. And therefore, a stage may have heap-alloca=
ted one=20
<br>&gt; of streams, or it may simply pass the object from the previous sta=
ge=20
<br>&gt; through.
<br>&gt;=20
<br>&gt; It&#39;s not clear to me why `unique_ptr` doesn&#39;t work here. M=
aybe I&#39;m missing=20
<br>&gt; something here.
<br>
<br>A stage may retain its input for later use. Or the caller of the
<br>pipeline may retain the input for whatever reason, and want to avoid
<br>needing to make a copy. (Maybe the original input came from a source
<br>that can&#39;t be coerced into a proper unique_ptr&lt;T&gt;, e.g. becau=
se we
<br>loaded the input as U, and can get a view T of the input, but can&#39;t=
 take
<br>ownership of the T. This can often happen if T is an array of primitive
<br>type and U is some library-specific container type.)
<br>
<br>&gt; How does using `unique_ptr` require copying of the data? It&#39;s =
just passing=20
<br>&gt; ownership of an object through to the next stage.
<br>
<br>...which precludes retaining ownership. Let&#39;s say we are talking ab=
out a
<br>stepped pipeline (fairly common, e.g. a video processing pipeline).
<br>Let&#39;s say that a particular stage&#39;s output is dependent on its =
previous
<br>output. Obviously, then, in the stage&#39;s internal state, it needs to
<br>retain a copy of its previous output (at least in some architectures).
<br>
<br>With unique_ptr, this means it has to make a copy of the output to pass
<br>to the next stage, since it is required to relinquish ownership. With
<br>optional_ptr, it can just return a non-owning pointer.
<br></blockquote><div><br></div><div>Doesn&#39;t this prove absolutely why =
optional_ptr is a bad idea? Let&#39;s say I have a pipeline stage</div><div=
><br></div><div>optional_ptr&lt;T&gt; A(optional_ptr&lt;T&gt; input)</div><=
div>{</div><div>=C2=A0 =C2=A0 static optional_ptr&lt;T&gt; saved =3D nullpt=
r;</div><div>=C2=A0 =C2=A0 compute_something_with(input, saved);</div><div>=
=C2=A0 =C2=A0 saved =3D std::move(input); =C2=A0// the original input is no=
w owned by me</div><div>=C2=A0 =C2=A0 return saved.get(); =C2=A0// return a=
 non-owning handle to the original input</div><div>}</div><div><br></div><d=
iv>then if I chain together a couple of calls =E2=80=94</div><div><br></div=
><div>=C2=A0 =C2=A0 optional_ptr&lt;T&gt; t1 =3D ...;</div><div>=C2=A0 =C2=
=A0 optional_ptr&lt;T&gt; t2 =3D A(std::move(t1));</div><div><div>=C2=A0 =
=C2=A0 optional_ptr&lt;T&gt; t3 =3D A(std::move(t2));</div></div><div><br><=
/div><div>t1 was an owning handle, but now it&#39;s moved-from.</div><div>A=
 took ownership of the t1-pointed object, saved ownership in `saved`, and p=
assed back a non-owning handle as t2.</div><div>Then the second A takes t2,=
 saves the non-owning handle in `saved` (remember, it can&#39;t tell the di=
fference between the owning pointer and a non-owning handle, by design), an=
d returns another non-owning handle.</div><div><br></div><div>However, when=
 the second A saved the non-owning handle in `saved`, it clobbered `saved`&=
#39;s OLD value, which is to say, the owning pointer to the original object=
! So that object&#39;s lifetime is now over, but we have these non-owning h=
andles still pointing to it. In other words, things are dangling all over t=
he place.</div><div><br></div><div>The smart pointer classes are designed s=
pecifically to eliminate this whole class of mistakes.</div><div>There&#39;=
s no sense in trying to wrap a might-be-owning-might-not-be-<wbr>owning poi=
nter in something that looks like a smart pointer class, because it fundame=
ntally is NOT a smart pointer; it&#39;s just a plain old might-be-owning-mi=
ght-not-be-<wbr>owning-might-be-dangling raw pointer. IF you want one of th=
ose, C++ already has them; they&#39;re spelled (T*).</div></blockquote><div=
><br></div><div>I&#39;m not sure where you guys are getting these insane de=
signs. That code doesn&#39;t even make sense. optional_ptr is not meant to =
be passed around willy nilly. Its meant to be used as a sink. In general yo=
u may be passing an optional_ptr to a function for final storage, but rarel=
y if ever returning it.</div><div><br></div><div>In my design, each stage r=
eceives a non-owning view to the input and owns his output. The external wo=
rld only deals in T*. A T* is passed in for the input, and a T* is exposed =
as the output. The clients of the interface are completely unburdened with =
memory management concerns.</div><div><br></div><div>Lets try this one more=
 time. We start with unique_ptr and a single stream:</div><div><br></div><d=
iv><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187)=
; word-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> stage </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">public</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br=
>=C2=A0stage</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> input</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><font color=3D"#008800"><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> _input</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">input</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">),</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> _output</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">make_un=
ique</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&gt;())</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{}</span></font><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0T</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> input</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _input</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 style=3D=
"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0T</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> output</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> _output</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">get</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br><br>=C2=A0</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> process_next</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"colo=
r: #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">private</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0T</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> _input</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><=
font color=3D"#000000"><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> _output</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span></=
font></div></code></div><br></div>Now suppose I want to have a stage which =
just passes through the input without doing anything. Using unique_ptr, tha=
t means I need to allocate a new output stream and copy the data.<div><br><=
/div><div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 18=
7, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><cod=
e class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> noop</span><font color=3D"#666600"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">_stage </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">public</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> stage </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> pr=
ocess_next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0_output</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">()-&gt;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">push_back</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">input</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">()-&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">back</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">());</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span></font></div></code></div><br>This of course is pointless=
 and wastes memory and cpu time. So instead lets use optional pointer and n=
ow the noop_stage can just passthrough his input and not do any computation=
 at all.</div><div><br></div><div class=3D"prettyprint" style=3D"border: 1p=
x solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(25=
0, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> stage </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">protected</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> <br>=C2=A0stage</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-b=
y-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> input</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> optional_=
ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> output</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> _input</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">input</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
),</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _output=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">move</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">output</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">))</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">public<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0T</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> input</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> _input</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0T</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> output</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
_output</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">get</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br><br>=C2=A0</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">virtual</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> process_next</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span><spa=
n 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"co=
lor: #008;" class=3D"styled-by-prettify">private</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0T</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> _input</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0optional_ptr</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 _output</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> noop</span><font color=3D"#6666=
00"><span style=3D"color: #000;" class=3D"styled-by-prettify">_stage </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">public</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> stage </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">public</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0noop_stage</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> input</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> stage</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">input</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> input</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">virtual</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> process_next</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>/* do nothing! */</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></font><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> real_stage </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">public</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> stage </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">public</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0real_stage</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> input</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> stage</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">input</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">make_unique</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&gt;())</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> process_next</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> output</span><font c=
olor=3D"#666600"><span style=3D"color: #660;" class=3D"styled-by-prettify">=
()-&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">pus=
h_back</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">transform</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">input</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()-&gt;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">back</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">()));</span><span style=3D"color: #00=
0;" 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"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span></font></div></code></div><div><font color=3D"#000000" st=
yle=3D"font-family: monospace; background-color: rgb(250, 250, 250);"><span=
 class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);"><br></span=
></font>With optional_ptr, we don&#39;t need to pollute our interface with =
shared_ptr. Clients are none the wiser and can safely deal with T* pointers=
 whose lifetimes are managed. This of course assumes the client manages the=
 lifetimes of the pipeline stages correctly, but of course in any sane syst=
em that part will also be handled by a higher level pipeline class which co=
rrectly manages the stages and continues to shield clients from the possibi=
lity of memory management bugs.</div><div><br></div><div><div class=3D"pret=
typrint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div=
 class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> pipeline </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">public</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0pipeline</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> input</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> _input</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">input</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0</span><fo=
nt color=3D"#000088"><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> input</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> _input</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
></font><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0T</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> output</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> _stages</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>empty</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">?</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> input</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> _stages</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">back</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
().</span><span style=3D"color: #000;" class=3D"styled-by-prettify">output<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">template</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> S</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ty=
pename</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Args</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> append_stage</span><font color=3D"#66=
6600"><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">S</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&amp;&amp;...</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> args</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></font><span style=3D"color: #000;" class=3D"styled-by-=
prettify">=C2=A0 _stages</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">push_back</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">make_unique</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">S</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;(</span><font color=3D"#000000=
"><span style=3D"color: #000;" class=3D"styled-by-prettify">output</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(),</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">forward</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">Args</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">args</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">)...</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span></font><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=
=A0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> process</span><fo=
nt color=3D"#666600"><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">_next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span></font><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 =C2=A0</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> s</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> _stages</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0s</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">process_=
next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">private</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0T</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> _input</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">vector</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">unique_pt=
r</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;</spa=
n><font color=3D"#000000"><span style=3D"color: #080;" class=3D"styled-by-p=
rettify">stage</span></font><span style=3D"color: #080;" class=3D"styled-by=
-prettify">&gt;</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
_stages</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">};</span></div></c=
ode></div><br></div>Of course for a single stream design like this, a noop_=
stage has little value outside of debugging and it doesn&#39;t make much se=
nse to alter the design to accomodate optimizing it. For a pipeline with mu=
ltiple inputs and outputs, where its common for many of them to not be tran=
sformed by every stage, being able to passthrough the inputs as outputs is =
critical to performance. I&#39;ll leave extending this code snippet for mul=
tiple inputs and outputs as an exercise for the reader.<br><div><br></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1285_571680889.1443155356252--
------=_Part_1284_3201277.1443155356250--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 25 Sep 2015 10:26:46 -0400
Raw View
On 2015-09-24 23:52, Arthur O'Dwyer wrote:
> Doesn't this prove absolutely why optional_ptr is a bad idea? Let's say I=
=20
> have a pipeline stage
>=20
> optional_ptr<T> A(optional_ptr<T> input)
> {
>     static optional_ptr<T> saved =3D nullptr;
>     compute_something_with(input, saved);
>     saved =3D std::move(input);  // the original input is now owned by me

This is wrong; 'saved' is now owned by you IFF 'input' was owned by you.

>     return saved.get();  // return a non-owning handle to the original in=
put
> }

Like many constructs, it's possible to misuse this. Holding a reference
to something you don't own is going to be dangerous without careful
design. A better design is:

  if (input.is_owned())
    saved =3D std::move(input);
  else
    saved =3D clone(input);

Getting a design like this correct and safe is not trivial, but absent a
construct like optional_ptr, you MUST make copies all the time (or use
shared_ptr and pay the cost both in doubled pointer size and atomic
reference counting).

> then if I chain together a couple of calls =E2=80=94
>=20
>     optional_ptr<T> t1 =3D ...;
>     optional_ptr<T> t2 =3D A(std::move(t1));
>     optional_ptr<T> t3 =3D A(std::move(t2));
>=20
> t1 was an owning handle, but now it's moved-from.

....and is now null, like unique_ptr.

> A took ownership of the t1-pointed object, saved ownership in `saved`, an=
d=20
> passed back a non-owning handle as t2.
> Then the second A takes t2, saves the non-owning handle in `saved`=20
> (remember, it can't tell the difference between the owning pointer and a=
=20
> non-owning handle, by design), and returns another non-owning handle.

Wait... what? Who said it *can't* tell the difference? That's *NOT* the
objective. The objective is to be able to use it without *caring* about
the difference (in cases where that makes sense).

> However, when the second A saved the non-owning handle in `saved`, it=20
> clobbered `saved`'s OLD value, which is to say, the owning pointer to the=
=20
> original object!

Not necessarily; at least in this case, self-assignment could trivially
prevent that happening. That said, this happens because your design is
flawed; if you intend to retain a non-owning reference, it is on your
head to ensure that the previous stage will not invalidate that
reference while you still need it.

> The smart pointer classes are designed specifically to eliminate this who=
le=20
> class of mistakes.
> There's no sense in trying to wrap a might-be-owning-might-not-be-owning=
=20
> pointer in something that looks like a smart pointer class, because it=20
> fundamentally is NOT a smart pointer; it's just a plain old=20
> might-be-owning-might-not-be-owning-might-be-dangling raw pointer. IF you=
=20
> want one of those, C++ already has them; they're spelled (T*).

A T* would be similarly unhelpful in your example; the memory would just
be leaked outright. However, it's not possible to fix your example using
T*. It *is* possible to use optional_ptr *correctly* in your example.

--=20
Matthew

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 29 Sep 2015 10:47:46 -0400
Raw View
--001a11c3124aa895580520e3e530
Content-Type: text/plain; charset=UTF-8

On Thu, Sep 24, 2015 at 12:35 PM, Matthew Fioravante <fmatthew5876@gmail.com
> wrote:

> For all resources, we have owners who manage the lifetime of the resource
> and viewers who view the resource. To be correct, all of the viewers have
> to stop using the pointer before the last owner goes out of scope and
> destroys the resource.
>
> For both unique_ptr and shared_ptr, the set of owners and viewers has to
> be decided explicitly ahead of time. This can very limiting because I've
> run into cases where I have types which 99% of the time are viewers
> (because the resource is often shared) but in some rare contexts need to be
> an owner because the object is being used standalone with no external
> entity to manage the ownership.
>
> The heavy handed solution to use shared_ptr everywhere. Now everyone is an
> owner. Using shared_ptr adds runtime overhead to manage the reference
> count. The biggest problem with shared_ptr is that once you use it in one
> place, you have to use it everywhere. Everything now must be dynamically
> allocated individually. You can't allocate 20 objects in an array and view
> one of them. You can't create objects on the stack or as a data member.
> Forcing individual dynamic allocation is a performance killer. We use C++
> because we need to be fast and a big part of being fast beings avoiding
> allocations or failing that, batching them into fewer allocations of large
> contiguous cache friendly chunks.
>
> The solution I'm toying with now is something called optional_ptr. Maybe
> its not such a great name because it could be confused with std::optional
> but lets leave bikeshedding aside for now.
>


If you are just toying with it now, come back in a year or so, and tell us
your experience.  We prefer standardizing things with lots of experience
behind it.  (And yes, I understand that you are somewhat asking if others
have similar experience.)

And I know you don't want to bikeshed, but please just don't call it
optional_ptr.  Maybe casual_ptr? (laidback_? hippie_?) ie "sure whatever
man, if you don't want it, I can delete it for you, but if you want to keep
it, that's OK too, I'll just use it for a moment, chill dude..."



>
> Essentially, optional_ptr is a move only type that works like
> a variant<T*,unique_ptr<T>>. You can construct it with a raw pointer for
> non-owning semantics or construct it with a unique_ptr to get owning
> semantics.
>
> The naive implementation of optional_ptr is to use T* and a bool, but for
> any type with alignof(T) > 1, you can actually store the ownership bit
> in lowest bit of the pointer itself since that bit will always be 0 due to
> alignment. The result is that OptionalPtr has minimal runtime overhead over
> unique_ptr/T* and for most types zero space overhead as well.
>
> Using optional_ptr means an entity has the flexibility to be either an
> owner or a viewer. Move only ensures unique ownership just like unique_ptr.
>
> Here is a sketch of what it might look like:
>
> template <typename T>
> class optional_ptr {
> public:
>   optional_ptr() = default;
>   optional_ptr(T* p) : _p(p), _own(false) {}
>   optional_ptr(unique_ptr<T> p) : _p(p.release()), _own(true) {}
>   ~optional_ptr() { if(_own) delete p; }
>
>   optional_ptr(const optional_ptr<T>&) = delete;
>   optional_ptr<T>& operator=(const optional_ptr<T>&) = delete;
>
>   optional_ptr(optional_ptr<T>&&) noexcept;
>   optional_ptr<T>& operator=(optional_ptr<T>&&) noexcept;
>
>   bool owns() const { return _own; }
>   T* get() const { return _p; }
>   T* release() noexcept { auto* p = _p; _own = false; _p = nullptr; return
> p; }
>   void reset(T* p);
>   void reset(unique_ptr<T> p);
>
>   //etc...
> private:
>   T* _p = nullptr;
>   bool _own = false;
> };
>
> How have you dealt with the problem of having a viewer which sometimes
> needs to be an owner? Do you see this as a valid problem that needs
> addressing or an anti-pattern?
>
>
>
>
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a11c3124aa895580520e3e530
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Thu, Sep 24, 2015 at 12:35 PM, Matthew Fioravante <span dir=3D"ltr">=
&lt;<a href=3D"mailto:fmatthew5876@gmail.com" target=3D"_blank">fmatthew587=
6@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><div>For all resources, we have=C2=A0owners wh=
o manage the lifetime of the resource and viewers who view the resource. To=
 be correct, all of the viewers have to stop using the pointer before the l=
ast owner goes out of scope and destroys the resource.</div><div>=C2=A0</di=
v><div>For both unique_ptr and shared_ptr, the set of owners and viewers ha=
s to be decided explicitly ahead of time. This can very limiting because I&=
#39;ve run into cases where I have types which 99% of the time are viewers =
(because the resource is often shared)=C2=A0but in some rare contexts need =
to be an owner because the object is being used standalone with no external=
 entity to manage the ownership.</div><div>=C2=A0</div><div>The heavy hande=
d solution to use shared_ptr everywhere. Now everyone is an owner. Using sh=
ared_ptr adds runtime overhead to manage the reference count. The biggest p=
roblem with shared_ptr is that once you use it in one place, you have to us=
e it everywhere. Everything now must be dynamically allocated individually.=
 You can&#39;t allocate 20 objects in an array and view one of them. You ca=
n&#39;t create objects on the stack or as a data member. Forcing individual=
 dynamic allocation is a performance killer. We use C++ because we need to =
be fast and a big part of being fast beings avoiding allocations or failing=
 that, batching them into fewer allocations of large contiguous cache frien=
dly chunks.</div><div>=C2=A0</div><div>The solution I&#39;m toying with now=
=C2=A0is something called optional_ptr. Maybe its not such a great name bec=
ause it could be confused with std::optional but lets leave bikeshedding as=
ide for now.</div></div></blockquote><div><br></div><div><br>If you are jus=
t toying with it now, come back in a year or so, and tell us your experienc=
e.=C2=A0 We prefer standardizing things with lots of experience behind it.=
=C2=A0 (And yes, I understand that you are somewhat asking if others have s=
imilar experience.)<br><br></div><div>And I know you don&#39;t want to bike=
shed, but please just don&#39;t call it optional_ptr.=C2=A0 Maybe casual_pt=
r? (laidback_? hippie_?) ie &quot;sure whatever man, if you don&#39;t want =
it, I can delete it for you, but if you want to keep it, that&#39;s OK too,=
 I&#39;ll just use it for a moment, chill dude...&quot;<br><br></div><div>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><div>=C2=A0</div><div>Essentially, optional_ptr is a move only typ=
e that works like a=C2=A0variant&lt;T*,unique_ptr&lt;T&gt;&gt;. You can con=
struct it with a raw pointer for non-owning semantics or construct it with =
a unique_ptr to get owning semantics. </div><div>=C2=A0</div><div>The naive=
 implementation of optional_ptr is to use T* and a bool, but for any type w=
ith alignof(T) &gt; 1, you can actually store the ownership bit in=C2=A0low=
est bit of the pointer itself since that bit will always be 0 due to alignm=
ent. The result is that OptionalPtr has minimal runtime overhead over uniqu=
e_ptr/T* and for most types zero space overhead as well.</div><div>=C2=A0</=
div><div>Using optional_ptr means an entity=C2=A0has the flexibility to be=
=C2=A0either an owner or a viewer. Move only ensures unique ownership just =
like unique_ptr.</div><div>=C2=A0</div><div>Here is=C2=A0a sketch of what i=
t might look like:</div><div><code></code>=C2=A0</div><div><code><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(0,0,0)"> </span><span style=3D"color:rgb(102,=
102,0)">&lt;</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)">&g=
t;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:r=
gb(0,0,136)">class</span><span style=3D"color:rgb(0,0,0)"> optional_ptr </s=
pan><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0=
,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">public</span><span sty=
le=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"><br>=
=C2=A0 optional_ptr</span><span style=3D"color:rgb(102,102,0)">()</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">default</span><span style=3D"color:rgb(102,102,0)">;</span><span=
 style=3D"color:rgb(0,0,0)"><br>=C2=A0 optional_ptr</span><span style=3D"co=
lor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span><span =
style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)"> p<=
/span><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">:</span><span style=
=3D"color:rgb(0,0,0)"> _p</span><span style=3D"color:rgb(102,102,0)">(</spa=
n><span style=3D"color:rgb(0,0,0)">p</span><span style=3D"color:rgb(102,102=
,0)">),</span><span style=3D"color:rgb(0,0,0)"> _own</span><span style=3D"c=
olor:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,136)">false</span=
><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(102,102,0)">{}</span><span style=3D"co=
lor:rgb(0,0,0)"><br>=C2=A0 optional_ptr</span><span style=3D"color:rgb(102,=
102,0)">(</span><span style=3D"color:rgb(0,0,0)">unique_ptr</span><span sty=
le=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,0)">T</=
span><span style=3D"color:rgb(102,102,0)">&gt;</span><span style=3D"color:r=
gb(0,0,0)"> p</span><span style=3D"color:rgb(102,102,0)">)</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">:</span=
><span style=3D"color:rgb(0,0,0)"> _p</span><span style=3D"color:rgb(102,10=
2,0)">(</span><span style=3D"color:rgb(0,0,0)">p</span><span style=3D"color=
:rgb(102,102,0)">.</span><span style=3D"color:rgb(0,0,0)">release</span><sp=
an style=3D"color:rgb(102,102,0)">()),</span><span style=3D"color:rgb(0,0,0=
)"> _own</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"=
color:rgb(0,0,136)">true</span><span style=3D"color:rgb(102,102,0)">)</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,=
0)">{}</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span style=
=3D"color:rgb(102,102,0)">~</span><span style=3D"color:rgb(0,0,0)">optional=
_ptr</span><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">if</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,=
0,0)">_own</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)">delete</sp=
an><span style=3D"color:rgb(0,0,0)"> p</span><span style=3D"color:rgb(102,1=
02,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 o=
ptional_ptr</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> optio=
nal_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=
=3D"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp=
;)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">delete</span><span style=3D"color:rgb(102,102,0)">;=
</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 optional_ptr</span><span=
 style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,0)"=
>T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp;</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">operator</=
span><span style=3D"color:rgb(102,102,0)">=3D(</span><span style=3D"color:r=
gb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> optional_ptr</sp=
an><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb=
(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp;)</span><spa=
n style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">delete</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"><br><br>=C2=A0 optional_ptr</span><span style=3D=
"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">optional_pt=
r</span><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D"colo=
r:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp;&amp;)<=
/span><span style=3D"color:rgb(0,0,0)"> noexcept</span><span style=3D"color=
:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 option=
al_ptr</span><span style=3D"color:rgb(102,102,0)">&lt;</span><span style=3D=
"color:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">&gt;&amp;</=
span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,=
136)">operator</span><span style=3D"color:rgb(102,102,0)">=3D(</span><span =
style=3D"color:rgb(0,0,0)">optional_ptr</span><span style=3D"color:rgb(102,=
102,0)">&lt;</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"=
color:rgb(102,102,0)">&gt;&amp;&amp;)</span><span style=3D"color:rgb(0,0,0)=
"> noexcept</span><span style=3D"color:rgb(102,102,0)">;</span><span style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 <br>=C2=A0 </span><span style=3D"color:rgb=
(0,0,136)">bool</span><span style=3D"color:rgb(0,0,0)"> owns</span><span st=
yle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">return</sp=
an><span style=3D"color:rgb(0,0,0)"> _own</span><span style=3D"color:rgb(10=
2,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 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)">get</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)">const</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"c=
olor:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">return</span><s=
pan style=3D"color:rgb(0,0,0)"> _p</span><span style=3D"color:rgb(102,102,0=
)">;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 T</span><=
span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)=
"> release</span><span style=3D"color:rgb(102,102,0)">()</span><span style=
=3D"color:rgb(0,0,0)"> noexcept </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)">auto</span><span style=3D"color:rgb(102,102,0)">*</span><span sty=
le=3D"color:rgb(0,0,0)"> p </span><span style=3D"color:rgb(102,102,0)">=3D<=
/span><span style=3D"color:rgb(0,0,0)"> _p</span><span style=3D"color:rgb(1=
02,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> _own </span><span styl=
e=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </sp=
an><span style=3D"color:rgb(0,0,136)">false</span><span style=3D"color:rgb(=
102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> _p </span><span style=
=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,0,136)">nullptr</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)">return</span><span style=3D"color:rgb(0,0,0)"> p</s=
pan><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"=
color:rgb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">void=
</span><span style=3D"color:rgb(0,0,0)"> reset</span><span style=3D"color:r=
gb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">T</span><span style=
=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)"> p</span=
><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0=
,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">void</span><span =
style=3D"color:rgb(0,0,0)"> reset</span><span style=3D"color:rgb(102,102,0)=
">(</span><span style=3D"color:rgb(0,0,0)">unique_ptr</span><span style=3D"=
color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,0)">T</span><=
span style=3D"color:rgb(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0=
,0)"> p</span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"=
color:rgb(0,0,0)"><br><br>=C2=A0 </span><span style=3D"color:rgb(136,0,0)">=
//etc...</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"c=
olor:rgb(0,0,136)">private</span><span style=3D"color:rgb(102,102,0)">:</sp=
an><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 T</span><span style=3D"color=
:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)"> _p </span><span =
style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(0,0,136)">nullptr</span><span style=3D"colo=
r:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </spa=
n><span style=3D"color:rgb(0,0,136)">bool</span><span style=3D"color:rgb(0,=
0,0)"> _own </span><span style=3D"color:rgb(102,102,0)">=3D</span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">false</s=
pan><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0=
,0,0)"> <br></span><span style=3D"color:rgb(102,102,0)">};</span><span styl=
e=3D"color:rgb(0,0,0)"><br></span></div></code></div><br>How have you dealt=
 with the problem of having a viewer which sometimes needs to be an owner? =
Do you see this as a valid problem that needs addressing or an anti-pattern=
?</code></div><span class=3D""><font color=3D"#888888"><code><div><span sty=
le=3D"color:rgb(0,0,136)"></span>=C2=A0</div></code><br><div>=C2=A0</div><d=
iv>=C2=A0</div></font></span></div><span class=3D""><font color=3D"#888888"=
>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c3124aa895580520e3e530--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 29 Sep 2015 11:38:06 -0700 (PDT)
Raw View
------=_Part_457_1624239566.1443551886585
Content-Type: text/plain; charset=UTF-8

I see this pattern quite often. Usually you want to keep the option open to send a pointer to a by value member to conserve allocations. Often in framework code when you want to keep options open for framework users.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_457_1624239566.1443551886585--

.


Author: Ross Smith <ross.smith@otoy.com>
Date: Wed, 30 Sep 2015 11:43:53 +1300
Raw View
On 2015-09-30 07:38, Bengt Gustafsson wrote:
> I see this pattern quite often. Usually you want to keep the option open to send a pointer to a by value member to conserve allocations. Often in framework code when you want to keep options open for framework users.
>

One place I frequently need an optionally-owning pointer is in simple
command line utilities, where the user can optionally supply a file name
to read from (or write to), with a filename of "-" traditionally meaning
"read from standard input" (or "write to standard output"). So a lot of
programs intended to be run from the command line start with code like
this (error checking skipped for simplicity):

         string filename = argv[1];
         shared_ptr<istream> in;
         if (filename == "-")
             in.reset(&cin, [] (void*) {});
         else
             in = make_shared<ifstream>(filename);
         string line;
         getline(*in, line);

Another situation where I used an optionally-owning pointer recently is
in an image manipulation class, where the image class object might own
the image buffer itself, or might be operating on an image owned by some
other entity.

Ross Smith


--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Wed, 30 Sep 2015 14:54:14 -0400
Raw View
On 2015-09-29 18:43, Ross Smith wrote:
> Another situation where I used an optionally-owning pointer recently is
> in an image manipulation class, where the image class object might own
> the image buffer itself, or might be operating on an image owned by some
> other entity.

Ack. It would be really useful if QImage worked like that... having to
either make a copy or separately track ownership of the data is a real pain.

I imagine there are various cases of data wrapping conversion where it's
useful to be able to optionally transfer ownership. (That said, a
problem I've run into there is when the original owner has some esoteric
mechanism for releasing the memory, e.g. because it is irrevocably owned
by some other wrapper class. But I think unique_ptr with a custom
deleter containing a bound value can deal with this.)

--
Matthew

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: j4cbo@dropbox.com
Date: Wed, 30 Sep 2015 13:32:57 -0700 (PDT)
Raw View
------=_Part_9712_1201513734.1443645178050
Content-Type: multipart/alternative;
 boundary="----=_Part_9713_1067917629.1443645178051"

------=_Part_9713_1067917629.1443645178051
Content-Type: text/plain; charset=UTF-8

On Thursday, September 24, 2015 at 9:35:28 AM UTC-7, Matthew Fioravante
wrote:
>
> The heavy handed solution to use shared_ptr everywhere. Now everyone is an
> owner. Using shared_ptr adds runtime overhead to manage the reference
> count. The biggest problem with shared_ptr is that once you use it in one
> place, you have to use it everywhere. Everything now must be dynamically
> allocated individually. You can't allocate 20 objects in an array and view
> one of them. You can't create objects on the stack or as a data member.
> Forcing individual dynamic allocation is a performance killer. We use C++
> because we need to be fast and a big part of being fast beings avoiding
> allocations or failing that, batching them into fewer allocations of large
> contiguous cache friendly chunks.
>

You can, with the shared_ptr aliasing constructor (which I just discovered
yesterday):
    std::shared_ptr<std::vector<Thing>> owner = ...;
    std::shared_ptr<Thing> viewer(owner, &(*owner)[5]);
    // viewer shares ownership of the vector but points to a specific
element

Or, less safe but potentially faster:
    std::vector<Thing> owner = ...;
    std::shared_ptr<Thing> viewer(std::shared_ptr<Thing>(), &owner[5]);
    // viewer owns no object (so no atomic inc/dec will happen) but points
to owner[5]

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_9713_1067917629.1443645178051
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, September 24, 2015 at 9:35:28 AM UTC-7, Matth=
ew Fioravante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div>The heavy handed solution to use shared_ptr everywhere. Now e=
veryone is an owner. Using shared_ptr adds runtime overhead to manage the r=
eference count. The biggest problem with shared_ptr is that once you use it=
 in one place, you have to use it everywhere. Everything now must be dynami=
cally allocated individually. You can&#39;t allocate 20 objects in an array=
 and view one of them. You can&#39;t create objects on the stack or as a da=
ta member. Forcing individual dynamic allocation is a performance killer. W=
e use C++ because we need to be fast and a big part of being fast beings av=
oiding allocations or failing that, batching them into fewer allocations of=
 large contiguous cache friendly chunks.</div></div></blockquote><div><br><=
/div><div>You can, with the shared_ptr aliasing constructor (which I just d=
iscovered yesterday):</div><div>=C2=A0 =C2=A0 std::shared_ptr&lt;std::vecto=
r&lt;Thing&gt;&gt; owner =3D ...;<br></div><div>=C2=A0 =C2=A0 std::shared_p=
tr&lt;Thing&gt; viewer(owner,=C2=A0&amp;(*owner)[5]);<br></div><div><div>=
=C2=A0 =C2=A0 // viewer shares ownership of the vector but points to a spec=
ific element</div></div><div><br></div><div>Or, less safe but potentially f=
aster:</div><div>=C2=A0 =C2=A0 std::vector&lt;Thing&gt; owner =3D ...;<br><=
/div><div>=C2=A0 =C2=A0 std::shared_ptr&lt;Thing&gt; viewer(std::shared_ptr=
&lt;Thing&gt;(), &amp;owner[5]);</div><div>=C2=A0 =C2=A0 // viewer owns no =
object (so no atomic inc/dec will happen) but points to owner[5]</div></div=
>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_9713_1067917629.1443645178051--
------=_Part_9712_1201513734.1443645178050--

.


Author: David Krauss <potswa@gmail.com>
Date: Thu, 1 Oct 2015 11:31:17 +0800
Raw View
--Apple-Mail=_A77BF755-6B22-41F4-8FF8-08FD54BBE6F9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9309=E2=80=9330, at 10:50 PM, Bengt Gustafsson <bengt.gusta=
fsson@beamways.com> wrote:
>=20
> How about generalizing this idea to a erased_ptr<T> which can be construc=
ted from a unique_ptr&&, a shared_ptr, a weak_ptr or a plain ptr + bool.
>=20
> Internally this could be mainly a variant over the different pointer type=
s, but with an operator-> which works as for any smart pointer. The pointer=
 + owned =3D=3D true constructor could maybe be equivalent to sending in a =
unique_ptr&&
>=20
> More thinking is definitely needed but intuitively it seemed to increase =
the usefulness to include also shared ownership in the mix.=20

This might as well be std::unique_ptr< T, std::function<void(T&)> >. All im=
plementations of std::function that I=E2=80=99ve seen are able to embed a s=
hared_ptr without going to the heap.=20

It would also be useful to have this as an idiomatic type, for example when=
 extracting a node from a std::list or a std::set. I.e., std::unique_ptr< T=
, unspecified > std::set<T>::extract( iterator ) where unspecified converts=
 to std::function<void(T&)>. The same goes for the currently missing functi=
on std::allocate_unique.

However,

1. It=E2=80=99s a bad idea to break the invariant that unique_ptr is owning=
, so that it=E2=80=99s safe to move from its referent. It does need a Boole=
an flag in addition to the deleter.
2. weak_ptr requires validation before use, which would add overhead to all=
 the other cases. It doesn=E2=80=99t even implement operator*. Perhaps that=
 support doesn=E2=80=99t belong.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_A77BF755-6B22-41F4-8FF8-08FD54BBE6F9
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9330, at 10:50 PM, Bengt Gustafsson &lt;<a href=3D"mailto:bengt.gust=
afsson@beamways.com" class=3D"">bengt.gustafsson@beamways.com</a>&gt; wrote=
:</div><br class=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"=
ltr" style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; =
font-variant: normal; font-weight: normal; letter-spacing: normal; line-hei=
ght: normal; orphans: auto; text-align: start; text-indent: 0px; text-trans=
form: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-t=
ext-stroke-width: 0px;" class=3D"">How about generalizing this idea to a er=
ased_ptr&lt;T&gt; which can be constructed from a unique_ptr&amp;&amp;, a s=
hared_ptr, a weak_ptr or a plain ptr + bool.<div class=3D""><br class=3D"">=
</div><div class=3D"">Internally this could be mainly a variant over the di=
fferent pointer types, but with an operator-&gt; which works as for any sma=
rt pointer. The pointer + owned =3D=3D true constructor could maybe be equi=
valent to sending in a unique_ptr&amp;&amp;</div><div class=3D""><br class=
=3D""></div><div class=3D"">More thinking is definitely needed but intuitiv=
ely it seemed to increase the usefulness to include also shared ownership i=
n the mix.&nbsp;</div></div></div></blockquote></div><br class=3D""><div cl=
ass=3D"">This might as well be <font face=3D"Courier" class=3D"">std::uniqu=
e_ptr&lt; T, std::function&lt;void(T&amp;)&gt; &gt;</font>. All implementat=
ions of <font face=3D"Courier" class=3D"">std::function</font> that I=E2=80=
=99ve seen are able to embed a <font face=3D"Courier" class=3D"">shared_ptr=
</font> without going to the heap.&nbsp;</div><div class=3D""><br class=3D"=
"></div><div class=3D"">It would also be useful to have this as an idiomati=
c type, for example when extracting a node from a <font face=3D"Courier" cl=
ass=3D"">std::list</font> or a <font face=3D"Courier" class=3D"">std::set</=
font>. I.e., <font face=3D"Courier" class=3D"">std::unique_ptr&lt; T, <i cl=
ass=3D"">unspecified </i>&gt; std::set&lt;T&gt;::extract( iterator )</font>=
 where&nbsp;<i style=3D"font-family: Courier;" class=3D"">unspecified</i>&n=
bsp;converts to <font face=3D"Courier" class=3D"">std::function&lt;void(T&a=
mp;)&gt;</font>. The same goes for the currently missing function <font fac=
e=3D"Courier" class=3D"">std::allocate_unique</font>.</div><div class=3D"">=
<br class=3D""></div><div class=3D"">However,</div><div class=3D""><br clas=
s=3D""></div><div class=3D"">1. It=E2=80=99s a bad idea to break the invari=
ant that <font face=3D"Courier" class=3D"">unique_ptr</font> is owning, so =
that it=E2=80=99s safe to move from its referent. It does need a Boolean fl=
ag in addition to the deleter.</div><div class=3D"">2. <font face=3D"Courie=
r" class=3D"">weak_ptr</font> requires validation before use, which would a=
dd overhead to all the other cases. It doesn=E2=80=99t even implement <font=
 face=3D"Courier" class=3D"">operator*</font>. Perhaps that support doesn=
=E2=80=99t belong.</div><div class=3D""><br class=3D""></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_A77BF755-6B22-41F4-8FF8-08FD54BBE6F9--

.


Author: David Krauss <potswa@gmail.com>
Date: Thu, 1 Oct 2015 11:33:29 +0800
Raw View
--Apple-Mail=_AECC617A-8EAD-43EB-8A82-52C9AAF1C6EA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9310=E2=80=9301, at 11:31 AM, David Krauss <potswa@gmail.co=
m> wrote:
>=20
> std::unique_ptr< T, std::function<void(T&)> >

Oops, deleters take a pointer, not a reference. Same difference though.

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_AECC617A-8EAD-43EB-8A82-52C9AAF1C6EA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9310=
=E2=80=9301, at 11:31 AM, David Krauss &lt;<a href=3D"mailto:potswa@gmail.c=
om" class=3D"">potswa@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-inte=
rchange-newline"><div class=3D""><span style=3D"font-family: Courier; font-=
size: 12px; font-style: normal; font-variant: normal; font-weight: normal; =
letter-spacing: normal; line-height: normal; orphans: auto; text-align: sta=
rt; text-indent: 0px; text-transform: none; white-space: normal; widows: au=
to; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display=
: inline !important;" class=3D"">std::unique_ptr&lt; T, std::function&lt;vo=
id(T&amp;)&gt; &gt;</span></div></blockquote></div><br class=3D""><div clas=
s=3D"">Oops, deleters take a pointer, not a reference. Same difference thou=
gh.</div><div class=3D""><br class=3D""></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_AECC617A-8EAD-43EB-8A82-52C9AAF1C6EA--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Tue, 6 Oct 2015 17:59:46 -0700 (PDT)
Raw View
------=_Part_5484_571177465.1444179586324
Content-Type: multipart/alternative;
 boundary="----=_Part_5485_1486665348.1444179586324"

------=_Part_5485_1486665348.1444179586324
Content-Type: text/plain; charset=UTF-8

I've found this optional_ptr to be very useful in practice. In most of my
use cases I just want to optionally store the resource into its final
destination and never touch the resource management logic again until the
parent container destructor destroys it for me. If you start passing and
returning optional_ptr's all over the place the logic would get really
nonsensical pretty fast as seen in peoples examples so don't do that.

There are enough real use cases and positive feedback to argue strongly for
this simple utility and overall idiom.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_5485_1486665348.1444179586324
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I&#39;ve found this optional_ptr to be very useful in prac=
tice. In most of my use cases I just want to optionally store the resource =
into its final destination and never touch the resource management logic ag=
ain until the parent container destructor destroys it for me. If you start =
passing and returning optional_ptr&#39;s all over the place the logic would=
 get really nonsensical pretty fast as seen in peoples examples so don&#39;=
t do that.<div><br></div><div>There are enough real use cases and positive =
feedback to argue strongly for this simple utility and overall idiom.</div>=
</div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_5485_1486665348.1444179586324--
------=_Part_5484_571177465.1444179586324--

.