Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
G
gtkmm
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 29
    • Issues 29
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 4
    • Merge Requests 4
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • GNOME
  • gtkmm
  • Issues
  • #38

Closed
Open
Opened Nov 19, 2018 by Daniel Boles@dbolesDeveloper

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!

Edited Nov 19, 2018 by Daniel Boles
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: GNOME/gtkmm#38