捕获仅在实现中使用的结构中的特征
Capturing a trait in a struct that is only used in the implementation
如何定义具有多态结构和与其相关联的特征的 struct
,但特征不影响 struct
定义,仅影响实现?
此处编译器拒绝接受 Interpreter
的定义,因为 Evaluator
未被使用,但在实现中是必要的:
pub trait StateEvaluator<State> {
fn eval(state: State, buf: &mut [u8]);
}
pub struct Interpreter<State, Evaluator> {
state: State
}
impl<State: Default, Evaluator: StateEvaluator<State>> Interpreter<State, Evaluator> {
pub fn new() -> Interpreter<State, Evaluator> {
Interpreter {
state: Default::default()
}
}
pub fn eval(&self, buf: &mut [u8]) {
Evaluator::eval(self.state, buf)
}
}
从 struct
中删除它会导致 impl
版本不匹配,并出现不同的编译器错误,即期望 1 个参数并得到 2 个参数。
您可以选择几个方向:
添加一个phantom data marker for Evaluator
:
use std::marker;
pub trait StateEvaluator<State> {
fn eval(state: State, buf: &mut [u8]);
}
pub struct Interpreter<State, Evaluator> {
state: State,
evaluator: marker::PhantomData<Evaluator>,
}
impl<State: Default + Clone, Evaluator: StateEvaluator<State>> Interpreter<State, Evaluator> {
pub fn new() -> Interpreter<State, Evaluator> {
Interpreter {
state: Default::default(),
evaluator: marker::PhantomData,
}
}
pub fn eval(&self, buf: &mut [u8]) {
Evaluator::eval(self.state.clone(), buf)
}
}
这样在结构中使用泛型类型。 (请注意,我已做出将 Clone
绑定到 State
的行政决定,以便 eval
可以将 State
传递给 StateEvaluator
;您可以也可以接受 &State
或 Copy
限制。)
将 Evaluator
泛型从类型转移到 eval
函数。这可能不是您想要的,但我会提到它。
pub trait StateEvaluator<State> {
fn eval(state: State, buf: &mut [u8]);
}
pub struct Interpreter<State> {
state: State,
}
impl<State: Default + Clone> Interpreter<State> {
pub fn new() -> Interpreter<State> {
Interpreter {
state: Default::default(),
}
}
pub fn eval<Evaluator: StateEvaluator<State>>(&self, buf: &mut [u8]) {
Evaluator::eval(self.state.clone(), buf)
}
}
类型参数Evaluator
被称为phantom type because it is not used in the type definition. Rust used to allow such code to compile, but a change earlier this year related to variance是非法的。相反,您必须使用类型参数。
要保留其幽灵性质,您可以使用 "marker" 之类的 PhantomData
。这是一种由编译器解释的特殊类型。
让您的代码正常工作很容易。只需添加一个使用您的幻像类型参数的 PhantomData
成员:
use std::marker::PhantomData;
pub struct Interpreter<State, Evaluator> {
state: State,
_marker: PhantomData<Evaluator>,
}
然后稍微调整结构:
Interpreter {
state: Default::default(),
_marker: PhantomData,
}
类型推断会自动填充 PhantomData
的类型参数。
如何定义具有多态结构和与其相关联的特征的 struct
,但特征不影响 struct
定义,仅影响实现?
此处编译器拒绝接受 Interpreter
的定义,因为 Evaluator
未被使用,但在实现中是必要的:
pub trait StateEvaluator<State> {
fn eval(state: State, buf: &mut [u8]);
}
pub struct Interpreter<State, Evaluator> {
state: State
}
impl<State: Default, Evaluator: StateEvaluator<State>> Interpreter<State, Evaluator> {
pub fn new() -> Interpreter<State, Evaluator> {
Interpreter {
state: Default::default()
}
}
pub fn eval(&self, buf: &mut [u8]) {
Evaluator::eval(self.state, buf)
}
}
从 struct
中删除它会导致 impl
版本不匹配,并出现不同的编译器错误,即期望 1 个参数并得到 2 个参数。
您可以选择几个方向:
添加一个phantom data marker for
Evaluator
:use std::marker; pub trait StateEvaluator<State> { fn eval(state: State, buf: &mut [u8]); } pub struct Interpreter<State, Evaluator> { state: State, evaluator: marker::PhantomData<Evaluator>, } impl<State: Default + Clone, Evaluator: StateEvaluator<State>> Interpreter<State, Evaluator> { pub fn new() -> Interpreter<State, Evaluator> { Interpreter { state: Default::default(), evaluator: marker::PhantomData, } } pub fn eval(&self, buf: &mut [u8]) { Evaluator::eval(self.state.clone(), buf) } }
这样在结构中使用泛型类型。 (请注意,我已做出将
Clone
绑定到State
的行政决定,以便eval
可以将State
传递给StateEvaluator
;您可以也可以接受&State
或Copy
限制。)将
Evaluator
泛型从类型转移到eval
函数。这可能不是您想要的,但我会提到它。pub trait StateEvaluator<State> { fn eval(state: State, buf: &mut [u8]); } pub struct Interpreter<State> { state: State, } impl<State: Default + Clone> Interpreter<State> { pub fn new() -> Interpreter<State> { Interpreter { state: Default::default(), } } pub fn eval<Evaluator: StateEvaluator<State>>(&self, buf: &mut [u8]) { Evaluator::eval(self.state.clone(), buf) } }
类型参数Evaluator
被称为phantom type because it is not used in the type definition. Rust used to allow such code to compile, but a change earlier this year related to variance是非法的。相反,您必须使用类型参数。
要保留其幽灵性质,您可以使用 "marker" 之类的 PhantomData
。这是一种由编译器解释的特殊类型。
让您的代码正常工作很容易。只需添加一个使用您的幻像类型参数的 PhantomData
成员:
use std::marker::PhantomData;
pub struct Interpreter<State, Evaluator> {
state: State,
_marker: PhantomData<Evaluator>,
}
然后稍微调整结构:
Interpreter {
state: Default::default(),
_marker: PhantomData,
}
类型推断会自动填充 PhantomData
的类型参数。