考虑以下二叉树代码
#[derive(Debug)]
struct Binary_Tree_Node<T: PartialOrd + Clone> {
left: Binary_Tree<T>,
value: T,
right: Binary_Tree<T>
}
#[derive(Debug)]
struct Binary_Tree<T: PartialOrd + Clone> {
node: Option<Box<Binary_Tree_Node<T>>>
}
impl <T: PartialOrd + Clone>Binary_Tree<T> {
fn new(value_to_insert: T) -> Binary_Tree<T> {
Binary_Tree{node:
Some(
Box::new(
Binary_Tree_Node{
left: Binary_Tree{node: None},
value: value_to_insert,
right: Binary_Tree{node: None}
}
)
)
}
}
fn map<F, U>(&self, f: F) -> Option<U>
where F: FnOnce(&Binary_Tree_Node<T>) -> U {
self.node.as_ref().map(|node| f(&**node))
// equivalent
//self.node.as_ref().map(|node| f(node))
}
}
let mut test1 = Binary_Tree::new(10);
println!("{:#?}", test1.map(|node| node.value < 2));
这条线让我很困惑
self.node.as_ref().map(|node| f(node))
因为我预计 rust 会抛出编译器错误
self.node
类型为 Option<Box<Binary_Tree_Node<T>>>
self.node.as_ref()
类型为 Option<&Box<Binary_Tree_Node<T>>>
node
在self.node.as_ref().map(|node| f(node))
类型为 &Box<Binary_Tree_Node<T>>
&Box<Binary_Tree_Node<T>>
不等同于通用约束 &Binary_Tree_Node<T>
问题是为什么self.node.as_ref().map(|node| f(&**node))
和 self.node.as_ref().map(|node| f(node))
工作?
最佳答案
这是一个“Deref 强制转换”,参见 nomicon Coercions :
Coercion is allowed between the following types:
- [...]
- Deref coercion: Expression
&x
of type&T
to&*x
of type&U
ifT
derefs toU
(i.e.T: Deref<Target=U>
)
Box<T>
工具 Deref<Target=T>
, 所以 &Box<T>
自动强制转换为 &T
就像你写的一样 &*node
.
(我不确定“表达式 &
”部分中的 &x
是做什么用的,因为我们在强制站点上没有 &
但它仍然有效 - 可能是拼写错误或错误)
也适用于 &String
至 &str
: Playground
fn foo<T>(_v: T) {}
fn main() {
{
let v: &Box<i32> = &Box::new(5i32);
foo::<&i32>(v);
foo::<&i32>(&*v);
}
{
let v: &String = &String::from("abc");
foo::<&str>(v);
foo::<&str>(&*v);
}
}
关于rust - Rust 编译器在多大程度上自动匹配泛型约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47547978/