此代码无法编译:
fn ref_on_int<T>(_: T) where T: AsRef<i32> {}
fn main() {
ref_on_int(&0_i32)
}
Run Code Online (Sandbox Code Playgroud)
因为
fn ref_on_int<T>(_: T) where T: AsRef<i32> {}
fn main() {
ref_on_int(&0_i32)
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
这可能对例如像这样的新类型很有用
struct MyInt(i32);
impl AsRef<i32> for MyInt {
/* etc. */
}
Run Code Online (Sandbox Code Playgroud)
那么您可以无差别地传递 an 上i32的引用或 a 上的引用MyInt,因为在这两种情况下我们都有一个i32.
AsRef和Borrow乍一看非常相似,但它们用于不同的事情。这本书很好地描述了它们之间的区别:
选择
Borrow何时要对不同类型的借用进行抽象,或者何时构建以等效方式(例如散列和比较)处理自有值和借用值的数据结构。选择
AsRef何时将某些内容直接转换为引用,并且您正在编写通用代码。
在您的情况下Borrow是更合理的选择,因为不涉及转换。
至于为什么AsRef不在不同的整数类型之间实现的问题,我想这与 Rust 表达强制转换的意图背道而驰;我认为这类似于为什么我不能比较两个不同类型的整数的问题?.
小智 5
这是Aaron Turon的权威回答:
Borrow提供了一个全面的实现T: Borrow<T>,这对于使上述集合运行良好至关重要。AsRef提供了一个不同的全面实现,基本上&T: AsRef<U>每当T: AsRef<U>,这对于像fs::open这样可以使用更简单、更灵活的签名的API 很重要。由于一致性,您不能同时拥有两个全面的实现,因此每个特征都在做出适合其用例的选择。