Reputation: 5686
The struct std::vec::Vec
implements two kinds of Extend, as specified here – impl<'a, T> Extend<&'a T> for Vec<T>
and impl<T> Extend<T> for Vec<T>
. The documentation states that the first kind is an "Extend implementation that copies elements out of references before pushing them onto the Vec". I'm rather new to Rust, and I'm not sure if I'm understanding it correctly.
I would guess that the first kind is used with the equivalent of C++ normal iterators, and the second kind is used with the equivalent of C++ move iterators.
I'm trying to write a function that accepts any data structure that will allow inserting i32
s to the back, so I take a parameter that implements both kinds of Extend
, but I can't figure out how to specify the generic parameters to get it to work:
fn main() {
let mut vec = std::vec::Vec::<i32>::new();
add_stuff(&mut vec);
}
fn add_stuff<'a, Rec: std::iter::Extend<i32> + std::iter::Extend<&'a i32>>(receiver: &mut Rec) {
let x = 1 + 4;
receiver.extend(&[x]);
}
The compiler complains that &[x]
"creates a temporary which is freed while still in use" which makes sense because 'a
comes from outside the function add_stuff
. But of course what I want is for receiver.extend(&[x])
to copy the element out of the temporary array slice and add it to the end of the container, so the temporary array will no longer be used after receiver.extend
returns. What is the proper way to express what I want?
Upvotes: 1
Views: 664
Reputation: 36071
From the outside of add_stuff
, Rect
must be able to be extended with a reference whose lifetime is given in the inside of add_stuff
. Thus, you could require that Rec
must be able to be extended with references of any lifetime using higher-ranked trait bounds:
fn main() {
let mut vec = std::vec::Vec::<i32>::new();
add_stuff(&mut vec);
}
fn add_stuff<Rec>(receiver: &mut Rec)
where
for<'a> Rec: std::iter::Extend<&'a i32>
{
let x = 1 + 4;
receiver.extend(&[x]);
}
Moreover, as you see, the trait bounds were overly tight. One of them should be enough if you use receiver
consistently within add_stuff
.
That said, I would simply require Extend<i32>
and make sure that add_stuff
does the right thing internally (if possible):
fn add_stuff<Rec>(receiver: &mut Rec)
where
Rec: std::iter::Extend<i32>
{
let x = 1 + 4;
receiver.extend(std::iter::once(x));
}
Upvotes: 2