С <T: Trait> Box<T>
вы используете типаж, связанный с сообщением компилятору, что вы хотите Box
с экземпляром некоторого типа T
, который реализует Trait
, и вы укажете T
при его использовании. Компилятор Rust, скорее всего, создаст другой эффективный код для каждого T
в вашем коде (мономорфизация).
С помощью Box<Trait>
вы сообщаете компилятору, что вам нужен Box
с типажным объектом, указателем на unknown тип, который реализует Trait
, что означает, что компилятор будет использовать динамическую отправку.
Я привел два примера, которые немного проясняют разницу:
<T: Trait> Box<T>
, т.е. привязка к признаку:
use std::fmt::Debug;
struct Wrapper<T> {
contents: Option<Box<T>>,
}
impl<T: Debug> Wrapper<T> {
fn new() -> Wrapper<T> {
Wrapper { contents: None }
}
fn insert(&mut self, val: Box<T>) {
}
}
fn main() {
let mut w = Wrapper::new();
// makes T for w be an integer type, e.g. Box<i64>
w.insert(Box::new(5));
// type error, &str is not an integer type
// w.insert(Box::new("hello"));
}
Box<Trait>
, то есть объект-признак:
use std::fmt::Debug;
struct Wrapper {
contents: Option<Box<Debug>>,
}
impl Wrapper {
fn new() -> Wrapper {
Wrapper { contents: None }
}
fn insert(&mut self, val: Box<Debug>) {
}
}
fn main() {
let mut w = Wrapper::new();
w.insert(Box::new(5));
w.insert(Box::new("hello"));
}
Для получения дополнительных сведений о различиях между границами признаков и объектами признаков я рекомендую раздел о свойствах в первом издании книги по Rust.
person
Erik Vesteraas
schedule
17.07.2017