Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 是否可以转换“借用<;T>;`至'AsRef<;T>;`反之亦然?_Rust - Fatal编程技术网

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())
}