为什么T没有实现AsRef ?

问题描述 投票:3回答:3

此代码无法编译:

fn ref_on_int<T>(_: T) where T: AsRef<i32> {}

fn main() {
    ref_on_int(&0_i32)
}

因为

the trait bound `i32: std::convert::AsRef<i32>` is not satisfied

为什么会这样?

例如,对于像new这样的新类型,这可能很有用

struct MyInt(i32);

impl AsRef<i32> for MyInt {
    /* etc. */
}

那么你可以无差别地传递关于i32MyInt上的引用的引用,因为在记忆中我们在两种情况下都有i32

rust
3个回答
3
投票

AsRefBorrow乍一看非常相似,但它们用于不同的事物。 The Book很好地描述了它们之间的区别:

当您想要抽象不同类型的借用时,或者当您构建一个以等效方式处理拥有和借用值的数据结构时,例如散列和比较,请选择Borrow

如果要直接将某些内容转换为引用,并选择编写通用代码,请选择AsRef

在你的情况下,Borrow是一个更合理的选择,因为没有涉及转换。

至于为什么AsRef没有在不同的整数类型之间实现的问题,我想这会违背Rust对于演员表达的意图;我认为这与问题Why can't I compare two integers of different types?相似。


3
投票

这是一个authoritative answer by Aaron Turon

Borrow提供了一个全面的实施T: Borrow<T>,这对于使上述收藏品运作良好至关重要。 AsRef提供了一个不同的毯子实现,基本上&T: AsRef<U>每当T: AsRef<U>,这对fs::open这样的API很重要,因为它可以使用更简单和更灵活的签名。由于连贯性,您不能同时使用这两种实现,因此每个特征都在做出适合其用例的选择。


2
投票

我认为这是AsRefBorrow的差异之一。

也就是说,Borrow<T>直接用于&T,而AsRef<T>没有用于&T

有趣的是,如果T实施AsRef<U>&T是为AsRef<U>实施的。也就是说,如果您可以将AsRef与类型一起使用,则可以在同一时间引用它。

另一个有趣的事情是Borrow<T>是为&T实施的,但也为T实施!

© www.soinside.com 2019 - 2024. All rights reserved.