Re: Replace Gtk::manage() with std::unique_ptr<>?



On 08/02/16 13:19 +0100, Murray Cumming wrote:
On Mon, 2016-02-08 at 11:56 +0000, Jonathan Wakely wrote:
[snip]
A cleaner API would operate in terms of rvalues returned from
functions, and passed straight into other functions, avoiding
std::move entirely.
[snip]

Do you mean like this?

 window.add(create_button("something"));

That's already possible by just taking a std::unique_ptr<> by value.

Yes, but it doesn't give you a non-owning pointer which can be used to
do other things to the button (either before or after adding it to the
window) which is what the thread was about. Your proposed patch in
Bugzilla has lots of TODO comments for use-after-move (which is
undefined behaviour and crashes).

What I'm saying is that those user-after-move need to be fixed by one
of:

(1) taking a raw pointer before transferring ownership by moving the
   unique_ptr, which you suggested at
   https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00011.html

(2) have the "add" functions return a raw pointer, as Diether suggested
   at
   https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00014.html

(3) add a helper that extracts a non-owning raw pointer as the rvalue
  passes by, as I suggested in
  https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00018.html


You said (1) "doesn't seem much better" than use-after-move, which I
disagree with. It's infinitely better because it is not undefined and
doesn't crash :-) But it's not ideal because it doesn't allow rvalues
to be passed straight from factory functions to sinks. You must create
an intermediate local variable, extract a raw pointer, then use
std::move to cast back to an rvalue.

Options (2) and (3) both allow rvalues to be passed straight from
factories to sinks, but allow a non-owning pointer to be obtained at
the same time.


However, I wouldn't want to enforce that if it forced people to write
code like this, without being able to break it up into separate lines:

 window.add(
   create_frame_with_children(
     create_label("something"),
     create_button("some button")));

It doesn't enforce anything. You always have the option of storing the
returned objects in local variables and moving them in, if that's what
you prefer.

But if you prefer *not* to do that, so that you don't need to use
std::move() and don't leave any empty unique_ptr objects lying around,
then only options (2) and (3) allow you to do that.

Option (1) enforces intermediate local variables.

Options (2) and (3) allow the programmer to choose.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]