Rust给Iterator<Item=...>类型字段赋值报错的原因及修复方案
错误原因
你定义的Abc<I>是泛型结构体,泛型参数I的具体类型由实例化Abc的调用方决定,只要满足I: Iterator<Item=u64>约束即可。比如调用方完全可以用Range<u64>、std::collections::hash_set::IntoIter<u64>等任意符合约束的迭代器类型作为I的实际类型。
而你在func1方法中硬编码将vec![1,2,3,4,5].into_iter()(也就是固定的std::vec::IntoIter<u64>类型)赋值给self.my_iter,相当于强行要求泛型I一定是std::vec::IntoIter<u64>,和泛型的设计逻辑冲突,所以编译器报类型不匹配错误。
修复方案
根据你的实际需求可以选择以下三种方案:
方案1:不需要泛型,固定使用vec迭代器
如果你的Abc结构体只需要存储vec生成的迭代器,直接去掉泛型,把字段类型写死即可:
struct Abc { my_iter: std::vec::IntoIter<u64>, } impl Abc { fn func1(&mut self) { self.my_iter = vec![1,2,3,4,5].into_iter(); } }
方案2:保留泛型,由外部传入迭代器
如果需要保留泛型支持任意迭代器类型,就不要在方法里硬编码生成迭代器,改为接收外部传入的符合类型的迭代器:
struct Abc<I> where I: Iterator<Item=u64> { my_iter: I, } impl<I> Abc<I> where I: Iterator<Item=u64> { fn func1(&mut self, iter: I) { self.my_iter = iter; } }
调用时传入对应类型的迭代器即可,比如abc.func1(vec![1,2,3].into_iter())。
方案3:使用特征对象动态分发,支持任意迭代器
如果不需要静态泛型的性能收益,希望灵活存储任意符合约束的迭代器,可以用特征对象:
struct Abc { my_iter: Box<dyn Iterator<Item = u64>>, } impl Abc { fn func1(&mut self) { self.my_iter = Box::new(vec![1,2,3,4,5].into_iter()); } }
这种方案不需要泛型参数,赋值时只要把迭代器装入Box即可,兼容所有满足Iterator<Item=u64>的迭代器类型。
内容的提问来源于stack exchange,提问作者Dmitry Rusakov
相关产品推荐
相关产品推荐

