On Fri, Jul 17, 2020 at 10:02 AM Ville Voutilainen via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Fri, 17 Jul 2020 at 04:35, Jefferson Carpenter via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
> > If `func` doesn't take ownership, why does it take a `ptr<T>` instead
> > of a `T*`? Can you give an example where using `ptr<T>` as an argument
> > to a function that doesn't take ownership is preferable to using `T*`?
> > I guess that would make it clearer what you're trying to accomplish.
>
> `func` takes a ptr because it is to take ownership if possible!  Taking
> a `ptr<T>` instead of a `T*` indicates that the function /can/ take
> ownership.
>
> Compare the previous example with
>
> func(make_ptr<Foo>());
>
> Here, func actually takes an owning pointer.  In this case, as soon as
> the ptr is nulled out somewhere in the execution of func, the instance
> of Foo is deleted.  This excludes being nulled out due to std::move - in
> that case ownership is handed off again.

Another way to look at it is that func doesn't take ownership nor not
take it (unless
it explicitly moves from the parameter in its definition); func just
uses the parameter,
and the lifetime of the parameter, and the cleanup at the end of it,
does the rest.
Thus there's not really any confusion about what func does wrt.
ownership, because
func actually doesn't do anything ownership-wise, all of that happens
in the initialization
of the parameter.

If I understand you correctly, I disagree.
IIUC, you're saying that there are two ways to use `func` here:
    void func(ptr<Foo> p);
    ... func(&local); ...  // construct a non-owning ptr
    ... func(make_ptr<Foo>(42)); ...  // construct an owning ptr, and then deallocate it afterward
So far so good. But then you say that we can think of `func` as not participating in ownership at all, just observing `*p`, and the important thing happening here is the RAII on the parameter variable.

But if that were actually the only use-case, then we wouldn't need ptr<T> at all! There's already an idiomatic C++ way of doing that:
    void betterfunc(Foo& f);
    ... betterfunc(local); ... // no ownership
    ... betterfunc(*std::make_unique<Foo>(42));  // construct an owning unique_ptr, and then deallocate it afterward
If the parameter `Foo& f` were const-qualified, we could even do this:
    ... betterfunc(Foo(42)); ... // construct a Foo and deallocate it afterward, without even using the heap!

So if "func doesn't do anything ownership-wise," then we don't need `ptr<T>` at all.
If `ptr<T>` has a use-case, it must involve doing something, ownership-wise.

–Arthur