【问题标题】:Using a Generic Trait over S<T> enforces me to have T outlive S在 S<T> 上使用 Generic Trait 强制我让 T 比 S
【发布时间】:2018-02-04 13:17:16
【问题描述】:

归结起来的问题如下:

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);
    }
}

Playground.

以上代码编译失败:

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&lt;'a&gt; 是一种寿命很短的数据类型(每帧一个),而LearningAlgorithm 是一种寿命很长的数据类型(多个游戏)。但是我实现这件事的方式,Rust 急切地相信,我传递给 print_learning_information 的每个 WorldState 都必须比 LearningAlgorithm 寿命长。

我做错了什么?不然怎么处理?

一些我不想做的事情:

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

【问题讨论】:

  • 问题似乎是暂时的。为什么不在第 60 行结束的范围内定义一个 var? let wstate = 5.; 之类的东西你的真实状态更复杂,所以可能已经存在了。
  • 问题是,内部范围实际上是游戏循环。我也许可以将状态作为我的游戏对象的变量,以便它在整个游戏中存活下来,我只是改变它。但是学习算法甚至可以在多个游戏中存活下来,我无法让游戏状态在所有游戏中都成为全局变量,因为唯一能活这么久的对象是学习算法,游戏对象是为每个游戏新创建的
  • 您的示例适用于夜间 Rust。我还不确定哪些更改使它可以编译。
  • 啊,那是PR 43838。在一般情况下它不会有帮助。

标签: rust lifetime ownership-semantics


【解决方案1】:

你的问题可以归结为

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 是类型构造函数,而不是具体类型。生命周期省略允许您编写 Box&lt;LearningAlgorithm&lt;WorldState&gt;&gt; 而不为 WorldState 显式指定生命周期参数,但这只是意味着编译器选择了一些适当的生命周期参数。

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

您需要对更高种类的类型的支持才能使您的示例按原样工作,但 Rust 不提供它。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2021-04-11
    • 2016-11-24
    • 2018-05-31
    • 1970-01-01
    • 2013-05-11
    相关资源
    最近更新 更多