Rust 是否可以转换“借用<;T>;`至'AsRef<;T>;`反之亦然?
我有一个变量Rust 是否可以转换“借用<;T>;`至'AsRef<;T>;`反之亦然?,rust,Rust,我有一个变量tokens:&[AsRef],我想把它连接成一个字符串: //令牌:&[AsRef] let text=tokens.join(“”//错误 让text=tokens.iter().map(|x | x.as_ref()).collect::().join(“”//好,但是。。。 第二种方法既笨拙又低效,因为它将项目重新分配到新的Vec 根据,join可以应用于令牌,如果其类型为和[Borrow]: //如果令牌:&[Borrow] 让text=tokens.join(“”//确
tokens:&[AsRef]
,我想把它连接成一个字符串:
//令牌:&[AsRef]
let text=tokens.join(“”//错误
让text=tokens.iter().map(|x | x.as_ref()).collect::().join(“”//好,但是。。。
第二种方法既笨拙又低效,因为它将项目重新分配到新的Vec
根据,join
可以应用于令牌
,如果其类型为和[Borrow]
:
//如果令牌:&[Borrow]
让text=tokens.join(“”//确定
//所以我想把&[AsRef]转换成&[Borrow]
let text=将\u转换为\u借用(令牌)。连接(“”)
我该怎么做?为什么对实现了
借用而不是AsRef
的类型实现了Join
?它可能稍微慢一点,但您可以将&str
的迭代器直接收集到字符串中
let text: String = tokens.iter().map(|s| s.as_ref()).collect();
这是可能的,因为。此方法通过反复调用push_str
来增长字符串,这可能意味着它必须重新分配多次,但它不会创建中间Vec
。根据所使用的切片和字符串的大小,这可能较慢(尽管在某些情况下也可能稍快)。如果差异对您来说意义重大,您应该对两个版本进行基准测试
没有办法把T:AsRef
的一个片段当作T:Borrow
的一个片段来对待,因为并不是所有实现AsRef
的东西都实现Borrow
,所以在泛型代码中,编译器不知道要应用什么Borrow
实现。可能会稍微慢一点,但是您可以将&str
的迭代器直接收集到字符串中
let text: String = tokens.iter().map(|s| s.as_ref()).collect();
这是可能的,因为。此方法通过反复调用push_str
来增长字符串,这可能意味着它必须重新分配多次,但它不会创建中间Vec
。根据所使用的切片和字符串的大小,这可能较慢(尽管在某些情况下也可能稍快)。如果差异对您来说意义重大,您应该对两个版本进行基准测试
没有办法将T:AsRef
的一片视为T:Borrow
的一片,因为不是所有实现AsRef
的东西都实现Borrow
,因此,在泛型代码中,编译器无法知道要应用什么借用实现。通过仅依赖AsRef
实现为您的实际问题提供解决方案。下面是对标题中更一般问题的回答
某些特性带有实现必须强制执行的不变量。特别是,如果借用
的实现也实现了Eq
、散列
和Ord
,那么T
的这些特性的实现必须表现相同。这一要求意味着借入价值与原值“相同”,但只是以不同的方式看待。例如,String:Borrow
实现必须返回整个字符串片段;返回子片是不正确的
AsRef
没有此限制。AsRef
的实现可以以与T
完全不同的方式实现诸如Hash
和Eq
之类的特性。如果只需要返回对结构一部分的引用,则AsRef
可以执行,而Borrow
不能执行
所有这一切意味着您无法从任意的AsRef
实现派生出有效的Borrow
实现:AsRef
实现可能不会强制执行Borrow
所需的不变量
然而,另一种方法确实有效。您可以创建一个AsRef
的实现,只要有一个任意的借用
:
使用标准::借用::借用;
使用std::convert::AsRef;
使用std::marker::PhantomData;
pub结构借用asref
哪里
T:借用+?大小,
U:?尺寸,
{
fn as_ref(&self)->&U{
self.0.borrow()
}
}
酒馆{
fn to_as_ref(&self)->借用asref{
借用ASREF(自我,幻影数据)
}
}
fn借用(v:&impl借用){
需要作为参考(&v.to作为参考())
}
fn需要作为参考(v:&impl AsRef){
println!(“as_ref:{:?}”,v.as_ref()
}
为什么对实现了Borrow
但未实现AsRef
的类型实现了Join
这是一个总括实现,适用于实现借用
的所有类型,这意味着它不能也适用于实现AsRef
的类型。即使启用了不稳定的特性min_specialization
,它也不会工作,因为实现AsRef
并不比实现Borrow
更“具体”。所以他们必须选择其中一个
可以说,AsRef
是一个更好的选择,因为它涵盖了更多的类型。但不幸的是,我认为现在无法改变这一点,因为这将是一个突破性的改变。通过仅依赖AsRef
实现,为您的实际问题提供了一个解决方案。下面是对标题中更一般问题的回答
某些特性带有实现必须强制执行的不变量。特别是,如果借用
的实现也实现了Eq
、散列
和Ord
,那么T
的这些特性的实现必须表现相同。这一要求意味着借入价值与原值“相同”,但只是以不同的方式看待。对于
fn borrowed(v: &impl Borrow<str>) {
needs_as_ref(&v.to_as_ref())
}
fn needs_as_ref(v: &impl AsRef<str>) {
println!("as_ref: {:?}", v.as_ref())
}