Enums 在枚举中将特征用作类型

Enums 在枚举中将特征用作类型,enums,polymorphism,rust,traits,Enums,Polymorphism,Rust,Traits,这是我的密码: 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

这是我的密码:

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),
    ...
}
两人都没有解决问题


我已经看到了使用泛型可能实现我想要的功能的方法,但是看起来两个具有不同运算符的表达式将是不同的类型,但这不是我想要的。我希望所有表达式都是相同的类型,无论运算符是什么。

特征没有已知的大小-它们没有大小。要了解原因,请查看以下内容:

性状附加{ fn添加一个&self->u8; } 结构阿尔法{ 答:u8, } 结构测试版{ 答:[u8;1024], } Alpha的impl AddOne{ fn添加一个&self->{0} } impl-AddOne测试版{ fn添加一个&self->{0} } Alpha和Beta都实现了AddOne,那么任意的AddOne应该有多大呢?哦,记住,在将来的某个时候,其他板条箱可能会实现你的特性

这就是为什么会出现第一个错误。有3种主要解决方案请注意,这些解决方案都不能立即解决您的问题…:

使用一个盒子。这与Java语言类似,但不同,Java语言只接受一个接口。它具有指针的已知大小,并拥有该特性。这样做的缺点是需要进行分配。 特征一元算子{ fn apply&self,expr:Expression->Expression; } 发布枚举表达式{ 一元框、表达式、, 价值64 } 使用对特征的引用。它还有一个已知的大小,一个指针值两个指针的值,请参阅。缺点是某些东西必须拥有该对象,并且您需要跟踪其生命周期: 特征一元算子{ fn应用->表达式{ 一元运算符,表达式; } 发布枚举表达式 其中U:一元运算符 { 一无所有,表情, 价值64 } 现在,由于您有一个递归类型定义,所有这些操作都会失败。让我们看看这个简化:

枚举表达式{ 表达, Bu8, } 表达式有多大?它需要有足够的空间来容纳…一个表达式!它需要能够容纳一个表达式…你看这是怎么回事

您需要在此处添加一些间接寻址。类似于1和2的概念适用-您可以使用方框或引用来获得固定大小:

枚举表达式{ ABox, Bu8, }
特征没有已知的大小-它们没有大小。要了解原因,请查看以下内容:

性状附加{ fn添加一个&self->u8; } 结构阿尔法{ 答:u8, } 结构测试版{ 答:[u8;1024], } Alpha的impl AddOne{ fn添加一个&self->{0} } impl-AddOne测试版{ fn添加一个&self->{0} } Alpha和Beta都实现了AddOne,那么任意的AddOne应该有多大呢?哦,记住,在将来的某个时候,其他板条箱可能会实现你的特性

这就是为什么会出现第一个错误。有3种主要解决方案请注意,这些解决方案都不能立即解决您的问题…:

使用方框。这类似于Java语言,但不同于Java语言,Java语言只接受一个接口。这有一个已知的大小,一个指针的值,并拥有这个特性。这有一个缺点,就是需要分配。 特征一元算子{ fn apply&self,expr:Expression->Expression; } 发布枚举表达式{ 一元框、表达式、, 价值64 } 使用对特征的引用。这也有一个已知的大小,一个指针值两个指针的值,请参阅。缺点是某些东西必须拥有该对象,并且您需要跟踪生命周期: 特征一元算子{ fn应用->表达式{ 一元运算符,表达式; } 发布枚举表达式 其中U:一元运算符 { 一无所有,表情, 价值64 } 现在,由于您有一个递归类型定义,所有这些操作都会失败。让我们看看这个简化:

枚举表达式{ 表达, Bu8, } 表达式有多大?它需要有足够的空间来容纳…一个表达式!它需要能够容纳一个表达式…你看这是怎么回事

您需要在此处添加一些间接寻址。类似于1和2的概念适用-您可以使用方框或引用来获得固定大小:

枚举表达式{ ABox, Bu8, }
然后,好像两个不同运算符的表达式将是不同的类型——我想你需要发布一个例子,我不太清楚你的意思。在你的答案中考虑解决方案3。如果我有两个不同的一元运算符A和B,那么一些表达式将是表达式,而其他表达式将是表达式。类型,对吗?假设我有一个表达式向量。这个向量必须是表达式向量或表达式向量。它不能两者都有。对吗?明白了。据我所知,你是对的。你可以创建一个表达式向量,但有ce
当然,这会带来一些额外的麻烦。那么,两个使用不同运算符的表达式可能会有不同的类型——我认为您需要发布一个这样的示例;我不太清楚你的意思。在你的答案中考虑解决方案3。如果我有两个不同的一元运算符,A和B,那么一些表达式将是表达式,另一些将是表达式。这些是不同类型的,对吗?假设我有一个表达式向量。该向量必须是表达式向量或表达式向量。不可能两者都有。对吗?明白了。据我所知,你是对的。您可以创建一个Vec,但肯定会有一些额外的麻烦。这也有一个已知的指针大小。=>实际上,有两个指针的值,它们是胖指针/引用,包含一个指向堆分配的数据部分的指针和一个指向v表ROM的指针。@MatthieuM。啊!我总是弄错。现在修好了,谢谢@马蒂厄姆。尽管如此,数据部分是否需要进行堆分配?我知道我见过一个trait引用,它似乎在堆栈上,比如let f1=ImplementsFoo::new;设f2:&Foo=&f1;数据部分不需要分配,“特征+”中的“a”是指数据部分的生存期实际上v表是“静态的”。这也有一个指针值的已知大小。=>实际上,有两个指针的值,它们是胖指针/引用,包含一个指向堆分配的数据部分的指针和一个指向v表ROM的指针。@MatthieuM。啊!我总是弄错。现在修好了,谢谢@马蒂厄姆。尽管如此,数据部分是否需要进行堆分配?我知道我见过一个trait引用,它似乎在堆栈上,比如let f1=ImplementsFoo::new;设f2:&Foo=&f1;数据部分不需要分配,“特征+”中的“a”是指数据部分的生命周期,实际上v表是“静态的”。