这是我的代码:
trait UnaryOperator {
fn apply(&self, expr: Expression) -> Expression;
}
pub enum Expression {
UnaryOp(UnaryOperator, Expression),
Value(i64)
}
其中包含以下错误:
error: the trait 'core::marker::sized' is not implemented for type 'parser::UnaryOperator'
note: 'parser::UnaryOperator' does not have a constant size known at compile-time
我不确定如何完成我想要的任务。我试过了:
trait UnaryOperator: Sized {
...
}
以及
pub enum Expression {
UnaryOp(UnaryOperator + Sized, Expression),
...
}
并没有解决问题。
我已经看到了通过泛型可能实现我想要的方法,但是看起来两个不同类型的表达式会有不同的类型,但这不是我想要的。无论运算符是什么,我都希望所有表达式都是相同的类型。
答案 0 :(得分:5)
特征没有已知的大小 - 它们是未分级。要了解原因,请查看:
trait AddOne {
fn add_one(&self) -> u8;
}
struct Alpha {
a: u8,
}
struct Beta {
a: [u8; 1024],
}
impl AddOne for Alpha {
fn add_one(&self) -> { 0 }
}
impl AddOne for Beta {
fn add_one(&self) -> { 0 }
}
Alpha
和Beta
都实现AddOne
,所以任意AddOne
应该有多大?哦,请记住,其他板条箱可能在将来的某个时候实施您的特性。
这就是你得到第一个错误的原因。有3个主要解决方案(请注意,这些解决方案都不能立即解决您的问题......):
Box<Trait>
。这与Java这样的语言有点相似但不同,你只接受一个接口。这具有已知的大小(指针的价值)并拥有该特征。这有需要分配的缺点。 trait UnaryOperator {
fn apply(&self, expr: Expression) -> Expression;
}
pub enum Expression {
UnaryOp(Box<UnaryOperator>, Expression),
Value(i64)
}
trait UnaryOperator {
fn apply<'a>(&self, expr: Expression<'a>) -> Expression<'a>;
}
pub enum Expression<'a> {
UnaryOp(&'a UnaryOperator, Expression<'a>),
Value(i64)
}
Expression<A>
和Expression<B>
会有不同的类型。根据您的使用情况,这可能是一个问题。如果您同时拥有Vec<Expression<A>>
,则无法轻松创建{.1}}。 trait UnaryOperator {
fn apply<U>(&self, expr: Expression<U>) -> Expression<U>;
}
pub enum Expression<U>
where U: UnaryOperator
{
UnaryOp(U, Expression<U>),
Value(i64)
}
现在,所有这些都失败了,因为你有一个递归类型定义。让我们来看看这个简化:
enum Expression {
A(Expression),
B(u8),
}
Expression
有多大?嗯,它需要有足够的空间来容纳...... Expression
!哪个需要能够持有Expression
....你会看到它的发展方向。
你需要在这里添加一些间接量。适用于#1和#2的类似概念 - 您可以使用Box
或引用来获得固定大小:
enum Expression {
A(Box<Expression>),
B(u8),
}