在 S 上使用通用特征<T>迫使我让 T 比 S 活得更久



归结的问题如下所示:

use std::marker::PhantomData;
struct WorldState<'a> {
state: &'a f64,
}
trait CalculateWorldState<T> {
fn state_value(&mut self, input: &T) -> f64;
}

trait LearningAlgorithm<T> {
fn print_learning_information(&self, &T);
}
struct EvolutionaryAlgorithm<F, T>
where
F: CalculateWorldState<T>,
{
//I need this since I only use T as a method parameter, I do not save it anywhere
//T are different ways to represent the current worldstate and are
//short-lived (new ones generated every frame)
_p_: PhantomData<T>,
//I don't actually need this one in the real example since I have
//an instatiated version of type CalculateWorldState saved in the
//struct but I use phantomdata for simplicity of the example
_p: PhantomData<F>,
}
impl<F, T> LearningAlgorithm<T> for EvolutionaryAlgorithm<F, T>
where
F: CalculateWorldState<T>,
{
fn print_learning_information(&self, input: &T) {
println!("My learning goes splendid!");
//do something with &T by calling the object of type
//CalculateWorldState which we have saved somewhere, but do
//not save the &T reference anywhere, just look at it
}
}
struct WorldIsInGoodState {}
impl<'a> CalculateWorldState<WorldState<'a>> for WorldIsInGoodState {
fn state_value(&mut self, input: &WorldState) -> f64 {
100.
}
}
fn main() {
let mut a: Box<LearningAlgorithm<WorldState>> =
Box::new(EvolutionaryAlgorithm::<WorldIsInGoodState, WorldState> {
_p: PhantomData,
_p_: PhantomData,
});
{
let state = WorldState { state: &5. };
a.print_learning_information(&state);
}
}

操场。

上面的代码编译失败:

error[E0597]: borrowed value does not live long enough
--> src/main.rs:59:5
|
57 |         let state = WorldState { state: &5. };
|                                          -- temporary value created here
58 |         a.print_learning_information(&state);
59 |     }
|     ^ temporary value dropped here while still borrowed
60 | }
| - temporary value needs to live until here

WorldState<'a>是一种生存期非常短的数据类型(每帧一个),而LearningAlgorithm是一种生存期很长的数据类型(多个游戏)。但是我实现这件事的方式,Rust 渴望相信,我传递给print_learning_information的每一WorldState都必须比LearningAlgorithm活得更久。

我做错了什么?否则如何处理?

我不想做的几件事:

  • WorldState包含正常状态(因为实际上它包含一些向量而不是f64,我不想在传递每个玩家自己的世界视图时将它们复制到WorldState结构中)
  • 只要退出这个项目并开始一个新的项目(你们都知道,在你投入了一些时间之后,你不想把所有的工作都扔掉)

您的问题可以归结为

struct WorldState<'a> {
state: &'a f64,
}
trait LearningAlgorithm<T> {
fn print_learning_information(&self, &T);
}
struct EvolutionaryAlgorithm();
impl<T> LearningAlgorithm<T> for EvolutionaryAlgorithm
{
fn print_learning_information(&self, input: &T) {
}
}
fn main() {
// scope a
let mut a: Box<LearningAlgorithm<WorldState>> =
Box::new(EvolutionaryAlgorithm());
{ // scope b
let val = 5.;
let state = WorldState { state: &val };
a.print_learning_information(&state);
}
}

请注意,WorldState是类型构造函数,而不是具体类型。生命周期 elision 允许您编写没有为WorldState显式指定生命周期参数的Box<LearningAlgorithm<WorldState>>,但它只是意味着编译器选择了一些适当的生命周期参数。

在这种情况下,为WorldState选择的生存期是scope a,因此a的类型是Box<LearningAlgorithm<WorldState<'scope_a>>>。因此,state应该有类型WorldState<'scope_a>,并且它包含的引用应该对scope a有效,但引用指向的值只存在于scope b中。

你需要支持更高级的类型来使你的示例按原样工作,但 Rust 没有提供它。

最简单的解决方案是通过用Rc替换引用来摆脱WorldState的生命周期参数。也许有人会想出更好的解决方案。

相关内容

  • 没有找到相关文章

最新更新