【发布时间】:2019-12-23 19:58:05
【问题描述】:
我有一个函数,它接受&T(由IntoIterator 表示)的集合,并要求每个元素都是唯一的。
fn foo<'a, 'b, T: std::fmt::Debug, I>(elements: &'b I)
where
&'b I: IntoIterator<Item = &'a T>,
T: 'a,
'b: 'a,
我还想编写一个包装函数,即使元素不是唯一的,它也可以工作,方法是先使用HashSet 删除重复的元素。
我尝试了以下实现:
use std::collections::HashSet;
fn wrap<'a, 'b, T: std::fmt::Debug + Eq + std::hash::Hash, J>(elements: &'b J)
where
&'b J: IntoIterator<Item = &'a T>,
T: 'a,
'b: 'a,
{
let hashset: HashSet<&T> = elements.into_iter().into_iter().collect();
foo(&hashset);
}
但是,编译器似乎对我假设 HashSet<&T> 实现 IntoIterator<Item = &'a T> 并不满意:
error[E0308]: mismatched types
--> src/lib.rs:10:9
|
10 | foo(&hashset);
| ^^^^^^^^ expected type parameter, found struct `std::collections::HashSet`
|
= note: expected type `&J`
found type `&std::collections::HashSet<&T>`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
我知道我可以通过克隆所有输入元素来使用HashSet<T>,但我想避免不必要的复制和内存使用。
【问题讨论】:
-
为什么你一生都在大惊小怪?看起来你好像挖了一个洞,然后继续前进。从提供的代码来看,没有理由拥有任何生命周期;请记住,泛型类型
X可以在其中包含一个引用。 example。您可能还对How do I write the lifetimes for references in a type constraint when one of them is a local reference? 感兴趣 -
我开始添加生命周期是因为编译器告诉我如果没有生命周期就添加生命周期:playground。如果我尝试使用泛型类型可以作为引用的事实,那么它想要执行移动而不是借用:playground
-
在这两个例子中,
&仍在函数签名/边界中。 example I provided 根本不使用它们;为什么还不够? -
这段代码没有意义。您提供对向量的引用,这会产生对项目的引用,但期望获得拥有的值,而无需复制或克隆值。你也不能这样使用
PhantomData