I ran into a rather subtle bug when using std::minmax
with structured bindings. It appears that passed rvalues will not always be copied as one might expect. Or
What's important to note in auto [amin, amax]
is that the auto
, auto&
and so forth are applied on the made up object e
that is initialized with the return value of std::minmax
, which is a pair. It's essentially this:
auto e = std::minmax(3, 6);
auto&& amin = std::get<0>(e);
auto&& amax = std::get<1>(e);
The actual types of amin
and amax
are references that refer to whatever std::get<0>
and std::get<1>
return for that pair object. And they themselves return references to objects long gone!
When you use std::tie
, you are doing assignment to existing objects (passed by reference). The rvalues don't need to live longer than the assignment expressions in which they come into being.
As a work around, you can use something like this (not production quality) function:
template
auto as_value(std::pair in) {
using U1 = std::decay_t;
using U2 = std::decay_t;
return std::pair(in);
}
It ensures the pair holds value types. When used like this:
auto [amin, amax] = as_value(std::minmax(3, 6));
We now get a copy made, and the structured bindings refer to those copies.