Use C++17 structured bindings instead of output arguments?
This applies to all unstable mm
libraries, but my examples are for gtkmm
, so I start here.
Can we make use of structured bindings or (in cases where the user wants to assign to existing variables and/or ignore returned values) std::tie()
, to get rid of some patterns where we currently return values through reference arguments to functions and/or custom structure types?
We might also want to add some convenience functions to make this as tidy as possible, at least in cases where the user will commonly want to ignore parts of compound return types, to avoid them having to redundantly (and possibly dangerously) separate the declaration and assignment of destination variables.
For example,
int minimum_width, natural_width;
widget.get_preferred_width(minimum_width, natural_width);
int window_x, window_y;
window.get_position(x, y);
could become
auto const [minimum_width, natural_width] = widget.get_preferred_width();
auto const [window_x, window_y] = window.get_position();
or
int natural_width, natural_height, ignore;
widget.get_preferred_width(ignore, natural_width);
widget.get_preferred_height(ignore, natural_height);
could become
int natural_width, natural_height;
std::tie(std::ignore, natural_width) = widget.get_preferred_width();
std::tie(std::ignore, natural_height) = widget.get_preferred_height();
...or, since that arguably isn't much better, this - avoiding separate declaration and assign, in a typical case where a user (me) often wants to ignore
something:
auto const [natural_width, natural_height] = widget.get_preferred_natural_size();
// and vice-versa for minimum_size
I've made some little helper functions to do these things for me, but they seem like things that will frequently be useful, especially as more people desire to write idiomatic C++17 and beyond, and they also seem equally or more viable than some of our other convenience API.
A frequent argument against returning things like tuple
or pair
is their lack of descriptive names. However, the same is true for function calls, and we've all managed to deal with that, so maybe it's not much of a problem. We would still want to document them, though...
I wonder if Doxygen has any support for annotating members of such structures by position, to ameliorate that? Alternatively, we could always still return custom structures with named members, as those (a) can be documented and (b) can still be decomposed by a structured binding declaration.
There are probably other/better examples than the above, but those are certainly some of the most frequently used output arguments, so it makes for a good start!