admin管理员组文章数量:1398826
I have an enum representing various actions that can be taken. However, some of its variants only makes sense in certain contexts, known at compile-time. To limit access to certain variants, I would like to add a const generic parameter to my enum like in the code below.
enum Action<const COND1: bool, const COND2: bool> {
A,
B,
C<enable if COND1>,
D<enable if COND2>,
}
let action1 = Action<false, false>::A;
match action1 {
Action<false, false>::A => {}
Action<false, false>::B => {}
}
let action2 = Action<true, false>::A;
match action2 {
Action<true, false>::A => {}
Action<true, false>::B => {}
Action<true, false>::C => {}
}
let action3 = Action<false, true>::A;
match action3 {
Action<false, true>::A => {}
Action<false, true>::B => {}
Action<false, true>::D => {}
}
Is this possible to achieve in rust?
I could create a separate enum for each combination, but that would result in a lot of duplicated code.
I have an enum representing various actions that can be taken. However, some of its variants only makes sense in certain contexts, known at compile-time. To limit access to certain variants, I would like to add a const generic parameter to my enum like in the code below.
enum Action<const COND1: bool, const COND2: bool> {
A,
B,
C<enable if COND1>,
D<enable if COND2>,
}
let action1 = Action<false, false>::A;
match action1 {
Action<false, false>::A => {}
Action<false, false>::B => {}
}
let action2 = Action<true, false>::A;
match action2 {
Action<true, false>::A => {}
Action<true, false>::B => {}
Action<true, false>::C => {}
}
let action3 = Action<false, true>::A;
match action3 {
Action<false, true>::A => {}
Action<false, true>::B => {}
Action<false, true>::D => {}
}
Is this possible to achieve in rust?
I could create a separate enum for each combination, but that would result in a lot of duplicated code.
Share Improve this question asked Mar 26 at 22:30 FredFred 4575 silver badges16 bronze badges 3 |2 Answers
Reset to default 5The never type can be used to "erase" variants that use a generic type, but this usage is not yet stabilized. On nightly:
#![feature(never_type)]
enum Action<C, D> {
A,
B,
C(C),
D(D),
}
You can use the ()
type to enable a variant and the !
type to disable it, so Action<!, ()>
would make the C
variant uninhabitable; matching on such a type would therefore not require the C
variant be considered.
Until !
is stabilized for this use, you can use an uninhabitable type like Infallible
(or any other empty enum) as a substitute for !
. Here is one way that you could do it:
type Enable = ();
type Disable = std::convert::Infallible;
enum Action<C, D> {
A,
B,
C(C),
D(D),
}
Now Action<Disable, Enable>
has the same properties as Action<!, ()>
would on nightly. Note the compiler is smart enough to figure out that the C
variant is uninhabitable even without usage of !
and so, like on nightly, match
does not require listing the uninhabitable variants.
(Once !
is stabilized you can keep the same source-compatible API by changing the Disable
alias to be !
instead of Infallible
.)
In the end, I solved my problem by implementing separate enums with a variant pointing to another enum:
#[derive(Clone, Serialize, Deserialize)]
enum Action1 {
A,
B,
}
#[derive(Clone, Serialize, Deserialize)]
enum Action2 {
C,
#[serde(untagged)]
Other(Action1),
}
#[derive(Clone, Serialize, Deserialize)]
enum Action3 {
D,
#[serde(untagged)]
Other(Action2),
}
By using #[serde(untagged)]
, that enum gets serialized as if the enum members inside the "Other" variant is part of the enum, which is what I actually wanted to accomplish.
本文标签: rustenabledisable enum variant with const generic parameterStack Overflow
版权声明:本文标题:rust - enabledisable enum variant with const generic parameter - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744123079a2591829.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
#[non_exhaustive]
enum with feature gates on certain variants. – JarroVGIT Commented Mar 28 at 7:24