Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
967 views
in Technique[技术] by (71.8m points)

rust - How can I box the contents of an iterator of a type that implements a trait?

I'm taking an iterator of some type that must implement the trait A, and trying to convert it into a Vec of Boxes of that trait:

trait A {}

fn test2<'a, I>(iterator: I) -> Vec<Box<A + 'a>>
where
    I: IntoIterator,
    I::Item: A + 'a,
{
    iterator
        .into_iter()
        .map(|a| Box::new(a))
        .collect::<Vec<Box<A + 'a>>>()
}

However, this fails to compile, saying:

error[E0277]: the trait bound `std::vec::Vec<std::boxed::Box<A + 'a>>: std::iter::FromIterator<std::boxed::Box<<I as std::iter::IntoIterator>::Item>>` is not satisfied
  --> src/main.rs:11:10
   |
11 |         .collect::<Vec<Box<A + 'a>>>()
   |          ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<A + 'a>>` cannot be built from an iterator over elements of type `std::boxed::Box<<I as std::iter::IntoIterator>::Item>`
   |
   = help: the trait `std::iter::FromIterator<std::boxed::Box<<I as std::iter::IntoIterator>::Item>>` is not implemented for `std::vec::Vec<std::boxed::Box<A + 'a>>`
   = help: consider adding a `where std::vec::Vec<std::boxed::Box<A + 'a>>: std::iter::FromIterator<std::boxed::Box<<I as std::iter::IntoIterator>::Item>>` bound

This error kind of makes sense, but then I don't see why there's no problem with the following:

fn test<'a, T: A + 'a>(t: T) -> Box<A + 'a> {
    Box::new(t)
}

How is that any different? How can I express that I'd like to Box them as As, rather than whatever type they may be?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to cast the Box<I::Item> into a Box<A>:

fn test2<'a, I>(iterator: I) -> Vec<Box<dyn A + 'a>>
where
    I: IntoIterator,
    I::Item: A + 'a,
{
    iterator
        .into_iter()
        .map(|a| Box::new(a) as Box<dyn A>)
        .collect()
}

How is [returning Box::new directly] any different?

As Sven Marnach points out:

The reason why you don't need an explicit cast in the function is that the last statement of a block is a coercion site and coercions happen implicitly at these sites. See the chapter on coercions in the nomicon for further details.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...