是否可以有一个结构,其中字段是枚举中的一个项目?锈
Is it possible to have a struct where the field is an item from an enum? Rust
是否可以有一个通用结构,使得结构中的项目是来自枚举的项目?例如:
enum AcceptableDataType {
String(String),
U8(u8),
}
struct Data<K, V>
where
K: AcceptableDataType,
V: AcceptableDataType,
{
map: HashMap<K, V>,
}
或者这是应该由特征处理的东西?我只是不确定如何以生锈的方式处理这种情况。
没有。有一个 RFC,Types for enum variants, but it was postponed:
While we may want to do something along these lines eventually, given the roadmap I think there is more pressing work on the language side, and this RFC has stalled.
惯用的方法就是使用负载类型(您可能需要为它创建一个结构)。喜欢:
struct Data<K, V> {
map: HashMap<K, V>,
}
Data<String, u8>
您可以使用特征来构建枚举,例如:
trait Enum<Variant>: Sized {
fn from_variant(v: Variant) -> Self;
fn into_variant(self) -> Option<Variant>;
fn as_variant(&self) -> Option<&Variant>;
fn as_variant_mut(&mut self) -> Option<&mut Variant>;
}
impl Enum<String> for AcceptableDataType {
fn from_variant(v: String) -> Self { Self::String(v) }
fn into_variant(self) -> Option<String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
fn as_variant(&self) -> Option<&String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
fn as_variant_mut(&mut self) -> Option<&mut String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
}
impl Enum<u8> for AcceptableDataType {
fn from_variant(v: u8) -> Self { Self::U8(v) }
fn into_variant(self) -> Option<u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
fn as_variant(&self) -> Option<&u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
fn as_variant_mut(&mut self) -> Option<&mut u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
}
struct Data<E, K, V>
where
E: Enum<K>,
E: Enum<V>,
{
map: HashMap<K, V>,
}
// etc.
请注意,此特性并不完美:如果两个变体具有相同的有效负载类型,则它不起作用。您也可以改进它以在这种情况下工作,还可以创建一个 proc 宏来轻松派生它。
如果我对你的问题的理解正确,你应该通过创建一个在 String
和 u8
.
上实现的特征来实现它。
trait AcceptableDataType {}
impl AcceptableDataType for String {}
impl AcceptableDataType for u8 {}
struct Data<K, V>
where
K: AcceptableDataType,
V: AcceptableDataType,
{
map: HashMap<K, V>,
}
请注意,在 Data
中,您不能只“检查”它是哪种类型,您只知道它是一个 AcceptableDataType
,它不会给您任何信息。
如果你需要取回两者的枚举,我会在特征中包含一个方法来这样做:
enum AcceptableDataTypeEnum {
String(String),
U8(u8),
}
trait AcceptableDataType {
fn into_enum(self) -> AcceptableDataTypeEnum;
}
并在 impls 中实现功能。
如果你不希望任何下游用户能够向特征添加新项目,你也可以sealed。
如果你有一组复杂的 impl,可能涉及重叠的泛型,但你只想将特征用作“标记”,那么你也可以使用不稳定的 night-only 特性 marker-trait-attr
.
但是请注意,这会阻止您在特征上使用方法,因此您不能使用上述方法取回枚举,您需要为此专门化,这是一个不完整的功能。
是否可以有一个通用结构,使得结构中的项目是来自枚举的项目?例如:
enum AcceptableDataType {
String(String),
U8(u8),
}
struct Data<K, V>
where
K: AcceptableDataType,
V: AcceptableDataType,
{
map: HashMap<K, V>,
}
或者这是应该由特征处理的东西?我只是不确定如何以生锈的方式处理这种情况。
没有。有一个 RFC,Types for enum variants, but it was postponed:
While we may want to do something along these lines eventually, given the roadmap I think there is more pressing work on the language side, and this RFC has stalled.
惯用的方法就是使用负载类型(您可能需要为它创建一个结构)。喜欢:
struct Data<K, V> {
map: HashMap<K, V>,
}
Data<String, u8>
您可以使用特征来构建枚举,例如:
trait Enum<Variant>: Sized {
fn from_variant(v: Variant) -> Self;
fn into_variant(self) -> Option<Variant>;
fn as_variant(&self) -> Option<&Variant>;
fn as_variant_mut(&mut self) -> Option<&mut Variant>;
}
impl Enum<String> for AcceptableDataType {
fn from_variant(v: String) -> Self { Self::String(v) }
fn into_variant(self) -> Option<String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
fn as_variant(&self) -> Option<&String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
fn as_variant_mut(&mut self) -> Option<&mut String> {
match self {
Self::String(v) => Some(v),
_ => None,
}
}
}
impl Enum<u8> for AcceptableDataType {
fn from_variant(v: u8) -> Self { Self::U8(v) }
fn into_variant(self) -> Option<u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
fn as_variant(&self) -> Option<&u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
fn as_variant_mut(&mut self) -> Option<&mut u8> {
match self {
Self::U8(v) => Some(v),
_ => None,
}
}
}
struct Data<E, K, V>
where
E: Enum<K>,
E: Enum<V>,
{
map: HashMap<K, V>,
}
// etc.
请注意,此特性并不完美:如果两个变体具有相同的有效负载类型,则它不起作用。您也可以改进它以在这种情况下工作,还可以创建一个 proc 宏来轻松派生它。
如果我对你的问题的理解正确,你应该通过创建一个在 String
和 u8
.
trait AcceptableDataType {}
impl AcceptableDataType for String {}
impl AcceptableDataType for u8 {}
struct Data<K, V>
where
K: AcceptableDataType,
V: AcceptableDataType,
{
map: HashMap<K, V>,
}
请注意,在 Data
中,您不能只“检查”它是哪种类型,您只知道它是一个 AcceptableDataType
,它不会给您任何信息。
如果你需要取回两者的枚举,我会在特征中包含一个方法来这样做:
enum AcceptableDataTypeEnum {
String(String),
U8(u8),
}
trait AcceptableDataType {
fn into_enum(self) -> AcceptableDataTypeEnum;
}
并在 impls 中实现功能。
如果你不希望任何下游用户能够向特征添加新项目,你也可以sealed。
如果你有一组复杂的 impl,可能涉及重叠的泛型,但你只想将特征用作“标记”,那么你也可以使用不稳定的 night-only 特性 marker-trait-attr
.
但是请注意,这会阻止您在特征上使用方法,因此您不能使用上述方法取回枚举,您需要为此专门化,这是一个不完整的功能。