Date: Fri, 17 Jul 2020 10:40:37 -0400
On Fri, Jul 17, 2020 at 10:02 AM Ville Voutilainen via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Fri, 17 Jul 2020 at 04:35, Jefferson Carpenter via Std-Proposals
> <std-proposals_at_[hidden]> 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
std-proposals_at_[hidden]> wrote:
> On Fri, 17 Jul 2020 at 04:35, Jefferson Carpenter via Std-Proposals
> <std-proposals_at_[hidden]> 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
Received on 2020-07-17 09:44:39