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?
You can also create and initialize a struct with a struct literal. An element list that contains keys does not need to have an element for each struct field. Omitted fields get the zero value for that field.
When initializing an object of struct or union type, the initializer must be a non-empty, (until C23) brace-enclosed, comma-separated list of initializers for the members: = { expression , ... }
// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'. For example, following is a valid initialization.
Initializing structure membersstruct car { char name[100]; float price; }; //car1 name as "xyz" //price as 987432.50 struct car car1 ={"xyz", 987432.50};
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 */
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With