我在使用 BTreeSet::range
方法时遇到了一些问题。
use std::collections::BTreeSet;
use std::ops::Bound::Included;
fn main() {
let set = BTreeSet::new();
set.insert("TEST1");
set.insert("TEST3");
set.insert("TEST4");
set.insert("TEST2");
set.insert("TEST5");
let bound = (Included("TEST3"), Included("TEST4"));
let rg = set.range(bound);
println!("result: {:?}", rg);
}
编译器提示:
error[E0283]: type annotations required: cannot resolve `_: std::cmp::Ord`
--> src/main.rs:14:18
|
14 | let rg = set.range(bound);
| ^^^^^
这是否意味着 &str
不能相互比较?
最佳答案
编译器无法推断出 K: Ord
的第一个通用参数 ( range
)来自 Included
的函数争论。
您需要明确指定它:
let rg = set.range::<&str, _>(bound);
为什么编译器无法推断出第一个泛型参数?
它实际上确实推断出类型,但是 K
有 2 个候选类型: 可以是 &'static str
或 str
. Rust 无法确定使用哪一个。
让我们分析一下 range
的定义方法来解释为什么 Rust 不能选择其中之一。
pub fn range<K: ?Sized, R>(&self, range: R) -> Range<'_, T>
where
K: Ord,
T: Borrow<K>,
R: RangeBounds<K>,
K
是一个动态大小的类型,T
可以表示为 K
和 R
是一个应该实现 RangeBounds<K>
的输入.
RangeBounds<T>
元组范围有 2 种不同的实现:
// first
impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>){}
在第一个 实现中,str
满足T
;它没有大小,住在 'static
生命周期。如果K
是 str
, 那么你可以有一个像这样的参数:(Inbound("val1"), Inbound("val2"))
// second
impl<T> RangeBounds<T> for (Bound<T>, Bound<T>){}
在第二个实现中,&str
满足T
.如果K
是 &str
那么你可以有一个像(Inbound("val1"), Inbound("val2"))
这样的论点
如您所见,两种类型的参数是相同的,Rust 有两个选项 K
.因此,它无法选择其中之一,因为这两个选项都适合,并且它希望您明确定义它。
let rg = set.range::<str, _>(bound);
这也将起作用,编译器将使用第一个 实现。由于两个实现做同样的事情,结果将是相同的。
另请参阅:
关于rust - 在一组 &str 上使用 BTreeSet::range 时需要类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54826252/