如何初始化相互引用的结构字段 [英] How to initialize struct fields which reference each other

查看:34
本文介绍了如何初始化相互引用的结构字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前想使用 GamerIterator 为 Piston 游戏定义一个结构:

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>,
    //...
}

GameIteratorGameWindow 及其生命周期中是通用的.我想告诉编译器它与字段game_window"/整个结构"具有相同的生命周期,而忽略结构的生命周期.

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.

我也很难初始化:

MyGame {
    game_window: GameWindowGLFW::new(GameWindowSettings {/*...*/},
    game_iter: GameIterator::new(&mut game_window, &game_iter_settings), // game_window cannot be used here
    //...
}

我认为我可以通过使用 Option<GameIterator<...>> 和 init() 方法来解决初始化问题,但我想避免这种情况,因为我可以保证 game_iternew() 完成后存在.

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?

推荐答案

如果 GameIterator 实现了 Drop:编译器必须知道它需要在 game_window 之前销毁 game_iter,否则 game_window 将引用被销毁的 GameWindowGLFW 同时运行其 drop() 方法.

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.

没有办法将结构本身的生命周期作为生命周期参数传递.您唯一能做的就是从 MyGame 中删除 game_window 字段并将 GameWindowGLFW 实例传递给 MyGame 的初始化程序.如果你想封装它以便用户不需要创建 GameWindowGLFW,你可以编写一个方法来创建一个 GameWindowGLFW 和一个 MyGame 并调用仅接受 MyGame 参数的闭包.

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

这篇关于如何初始化相互引用的结构字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆