I currently want to define a struct for a Piston game using GamerIterator:
pub struct MyGame<'a> {
game_window: GameWindowGLFW,
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
The GameIterator
is generic in the GameWindow
and its lifetime. I want to tell the compiler that it has the same lifetime as the field "game_window"/"the whole struct" and leave out the lifetime for the struct.
I also have difficulties initializing this:
MyGame {
game_window: GameWindowGLFW::new(GameWindowSettings {/*...*/},
game_iter: GameIterator::new(&mut game_window, &game_iter_settings), // game_window cannot be used here
//...
}
I think that I can work around the initialization issue by using Option<GameIterator<...>>
and an init() method, but I would like to avoid this because I can guarantee that game_iter
is present after new()
finishes.
What is the idiomatic way to write this?
Not only is there an issue with initialization, there could also be issues with destruction, if GameIterator
implemented Drop
: the compiler would have to know that it needs to destruct game_iter
before game_window
, otherwise game_window
would have a reference to a destroyed GameWindowGLFW
while running its drop()
method.
There's no way to pass the lifetime of the struct itself as a lifetime argument. The only thing you can do is remove the game_window
field from MyGame
and pass a GameWindowGLFW
instance to MyGame
's initializer. If you want to encapsulate this so that the user doesn't need to create a GameWindowGLFW
, you could write a method that creates a GameWindowGLFW
and a MyGame
on the stack and calls a closure that accepts a MyGame
argument only.
pub struct MyGame<'a> {
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
impl<'a> MyGame<'a> {
fn new(game_window: &'a mut GameWindowGLFW) -> MyGame<'a> {
MyGame {
game_iter: GameIterator { game_window: game_window },
}
}
}
fn start_game(callback: |game: &mut MyGame|) {
let mut game_window = GameWindowGLFW;
let mut game = MyGame::new(&mut game_window);
callback(&mut game);
}
fn main() {
start_game(|game| {
/* use game here */
});
}