【发布时间】:2019-12-26 17:30:39
【问题描述】:
TL;DR 嵌套对象的生命周期存在问题。代码如下。
加长版:
我正在使用ggez 编写多人游戏,并且我正在尝试为输入创建一个抽象层(以允许本地和远程玩家一起玩)。
为此,我创建了一个Input trait,并为本地输入实现了KeyboardInput,它使用ggez 键盘状态查询方法。
现在棘手的部分是:ggez 在启动时创建 Context 对象,并期望在大多数公开的函数中引用它。
因为我的KeyboardInput 实现是使用ggez 输入法(特别是is_key_pressed),所以它必须将&Context 传递给这个方法。但是,由于 trait 本身应该是通用的,因此任何其他实现都不需要 Context 引用(例如,NetworkInput)。
我的解决方案是在KeyboardInput 结构中添加对Context 的引用作为字段。但是,这导致了我仍然无法解决的终身错误。
我也尝试过使用'static,但这也没有用。
这里是相关代码:
pub trait Input {
fn get_direction(&self) -> Direction;
}
pub struct KeyboardInput<'a> {
left_key: KeyCode,
right_key: KeyCode,
_ctx: &'a Context
}
impl KeyboardInput<'_> {
pub fn new(_ctx: &Context, left_key: KeyCode, right_key: KeyCode) -> KeyboardInput {
KeyboardInput{
_ctx,
left_key,
right_key
}
}
}
impl Input for KeyboardInput<'_> {
fn get_direction(&self) -> Direction {
if ggez::input::keyboard::is_key_pressed(self._ctx, self.left_key) {
return Direction::Left;
}
if ggez::input::keyboard::is_key_pressed(self._ctx, self.right_key) {
return Direction::Right;
}
Direction::Unchanged
}
}
struct Player {
angle: f32,
pos_x: f32,
pos_y: f32,
input_manager: Box<dyn Input>,
}
impl <'a>MainState {
fn new(ctx: &'a Context) -> GameResult<MainState> {
let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
let kbd_input = Box::new(kbd_input);
let s = MainState {
last_update: Instant::now(),
players: vec![
Player::new(kbd_input)
]
};
Ok(s)
}
}
pub fn main() -> GameResult {
let cb = ggez::ContextBuilder::new("My game", "ggez");
let (ctx, event_loop) = &mut cb.build()?;
let state = &mut MainState::new(&ctx)?;
event::run(ctx, event_loop, state)
}
和编译器错误:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:75:25
|
75 | let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 72:7...
--> src\main.rs:72:7
|
72 | impl <'a>MainState {
| ^^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:75:44
|
75 | let kbd_input = KeyboardInput::new(ctx, KeyCode::Left, KeyCode::Right);
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn input_manager::Input + 'static)>
found std::boxed::Box<dyn input_manager::Input>
【问题讨论】: