为什么T没有实现AsRef <t>?

时间:2018-02-20 14:24:02

标签: rust

此代码无法编译:

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

为什么会这样?

例如,对于像

这样的新类型,这可能很有用
struct MyInt(i32);

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

然后你可以无动于衷地传递i32上的引用或MyInt上的引用,因为在内存中我们都有i32

3 个答案:

答案 0 :(得分:3)

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

  

如果要抽象不同类型,请选择Borrow   借用,或者当你构建一个对待所拥有的数据结构时   并以等价的方式借用价值,例如哈希和   比较。

     

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

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

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

答案 1 :(得分:3)

这里是authoritative answer by Aaron Turon

  

Borrow提供了一个全面的实现T: Borrow<T>,它是必不可少的,用于使上述集合正常工作。 AsRef提供了一个不同的覆盖实现,基本上是&T: AsRef<U>的{​​{1}},这对于像T: AsRef<U>这样可以使用更简单,更灵活的签名的API来说非常重要。由于一致性,您不能同时拥有全部的实现,因此每个特征都在做出适合其用例的选择。

答案 2 :(得分:2)

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

也就是说,Borrow<T>直接针对&T实施,而AsRef<T>未针对&T实施。

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

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