Is there a good way to use std::tie
and allocate memory at the same time? In other words, if a function returns a std:tuple
and we want to ultimately break up the result into individual components, is there a way to do these assignments without preallocating memory?
For example, consider the following code:
#include <tuple>
#include <limits>
struct Foo {
int val;
Foo(int const & val_) : val(val_) {}
Foo() = delete;
~Foo() = default;
Foo(Foo && foo) {
val = foo.val;
foo.val = std::numeric_limits <int>::min();
}
Foo & operator = (Foo && foo) {
val = foo.val;
foo.val = std::numeric_limits <int>::min();
return *this;
}
Foo(Foo const &) = default;
Foo & operator = (Foo const &) = default;
};
struct Bar {
Foo foo;
int lav;
Bar(int const & val_,int const & lav_) : foo(val_), lav(lav_) {}
Bar() = delete;
~Bar() = default;
Bar(Bar &&) = default;
Bar & operator = (Bar &&) = default;
Bar(Bar const &) = default;
Bar & operator = (Bar const &) = default;
};
std::tuple <Foo,Bar&&> f(Bar && bar) {
Foo foo = std::move(bar.foo);
return std::tuple<Foo,Bar&&> (foo,std::move(bar));
}
int main() {
auto bar = Bar(1,2);
#if 1
auto foo_bar = f(std::move(bar));
auto foo = std::move(std::get<0>(foo_bar));
bar = std::move(std::get<1>(foo_bar));
#else
Foo foo; // Doesn't work because foo has no default constructor
std::tie(foo,bar) = f(std::move(bar));
#endif
int junk=1;
}
Basically, the function f
extracts the foo
element from the object bar
and returns it separately. Using gdb, we see this works as expected:
42 auto foo_bar = f(std::move(bar));
(gdb) n
43 auto foo = std::move(std::get<0>(foo_bar));
(gdb)
44 bar = std::move(std::get<1>(foo_bar));
(gdb)
50 int junk=1;
(gdb) print foo
$1 = {val = 1}
(gdb) print bar
$2 = {foo = {val = -2147483648}, lav = 2}
Nevertheless, here, we allocated into the tuple foo_bar
first and then extracted the elements one at a time. Instead, we could try to use std::tie
by using the other side of the ifdef
. However, it doesn't work because we don't have a default constructor for foo
.
Now, in this case, we could just allocate a foo
by giving it a default constructor or by giving it a dummy value for its existing constructor. However, in general, this has been an issue for me since I have more complicated classes that don't have easy constructors. Really, I'd like to just have a statement like std::tie
that pushes a tuple into individual elements and allocates memory at the same time. Is this possible?
Aucun commentaire:
Enregistrer un commentaire