Rust 是否有一种安全、符合人体工程学的方法来改变复杂结构中的幻影类型?
假设我们定义了一个具有许多字段的泛型结构,它表示使用幻象类型的类型安全状态机:Rust 是否有一种安全、符合人体工程学的方法来改变复杂结构中的幻影类型?,rust,phantom-types,Rust,Phantom Types,假设我们定义了一个具有许多字段的泛型结构,它表示使用幻象类型的类型安全状态机: structfoo{ a:a, b:b, c:c, //... 状态:幻影数据, } 然后,我们可以编写类型安全状态转换: impl Foo<SourceState> { fn transition(self, extra: X) -> Foo<DestinationState> { let Foo {a, b, c, state: _} = self;
structfoo{
a:a,
b:b,
c:c,
//...
状态:幻影数据,
}
然后,我们可以编写类型安全状态转换:
impl Foo<SourceState> {
fn transition(self, extra: X) -> Foo<DestinationState> {
let Foo {a, b, c, state: _} = self;
// do lots of stuff
Foo { a, b, c, state: PhantomData }
}
}
impl-Foo{
fn转换(自身,额外:X)->Foo{
设Foo{a,b,c,state:{}=self;
//做很多事情
Foo{a,b,c,state:PhantomData}
}
}
但我们需要笨拙地将每个字段解包,并以不同的结构重新打包
我们也可以使用mem::transmute
,尽管我的理解是,同一结构的不同单体不能保证具有相同的内存布局
我希望,Foo{state:PhantomData,…self}
能起作用;唉,它无法编译
有没有什么规范的、符合人体工程学的、安全的方法来写这篇文章?没有直接的方法来写,因为它们有两种不同的类型:实际上,这就是代码的全部要点。为了简化它,我将分两步进行,第二步是一般转换:
use core::marker::PhantomData;
struct Foo<State> {
a: i32,
b: i32,
c: i32,
//...
state: PhantomData<State>,
}
struct SourceState;
struct DestinationState;
impl<Src> Foo<Src> {
fn transition<Dest>(self) -> Foo<Dest> {
let Foo {a, b, c, state: _} = self;
Foo { a, b, c, state: PhantomData }
}
}
impl Foo<SourceState> {
fn to_destination_state(mut self, extra: ()) -> Foo<DestinationState> {
// Do whatever you want with self
self.transition()
}
}
使用core::marker::PhantomData;
结构Foo{
a:i32,
b:i32,
c: i32,
//...
状态:幻影数据,
}
结构源状态;
结构目标状态;
impl-Foo{
fn转换(自)->Foo{
设Foo{a,b,c,state:{}=self;
Foo{a,b,c,state:PhantomData}
}
}
impl-Foo{
fn到目的地状态(多个自身,额外:())->Foo{
//你想怎么做就怎么做
self.transition()
}
}
或者,您可以抽象出您拥有一个状态的事实:
mod stateful {
use core::marker::PhantomData;
pub struct Stateful<T, State> {
pub data: T,
state: PhantomData<State>,
}
impl<T, SrcState> Stateful<T, SrcState> {
pub fn transform<DestState>(self) -> Stateful<T, DestState> {
let Stateful { data, state: _ } = self;
Stateful {
data,
state: Default::default(),
}
}
}
}
struct Data {
a: i32,
b: i32,
c: i32,
}
struct SourceState;
struct DestinationState;
type Foo<State> = stateful::Stateful<Data, State>;
impl Foo<SourceState> {
fn to_destination_state(mut self, extra: ()) -> Foo<DestinationState> {
// Do whatever you want with self.data
self.transform()
}
}
mod stateful{
使用core::marker::PhantomData;
pub结构有状态{
发布数据:T,
状态:幻影数据,
}
有状态的{
pub-fn转换(自)->有状态{
设有状态{data,state:{}=self;
有状态{
数据,
状态:Default::Default(),
}
}
}
}
结构数据{
a:i32,
b:i32,
c:i32,
}
结构源状态;
结构目标状态;
类型Foo=stateful::stateful;
impl-Foo{
fn到目的地状态(多个自身,额外:())->Foo{
//用self.data做任何你想做的事情
self.transform()
}
}
如果你的状态类型是零大小的,你不需要一个幻影数据
,或者我不明白什么请添加SourceState
和DestinationState
@Boiethios的定义你是对的,在这种情况下我的状态类型是单位类型,但是使用PhantomData比为我所有的状态实现默认值要短。第一个解决方案是我最终要做的。一个次要问题是:为什么结构省略语法需要类型的标识?它是否可以取消一组访问并删除此约束?或者这会在实践中破坏太多的类型推断吗?因此,如果不复制数据,就无法做到这一点?@user1685095你是什么意思?我的代码片段中没有一个副本。