首页 > 解决方案 > 使用 std::variant 或 std::optional 时 SDL 窗口立即关闭

问题描述

我正在尝试为 SDL2 应用程序创建一个简单的渲染器,并认为我会尝试将SDL_*资源unique_ptr与其作为删除器的SDL_Destroy*功能一起包装,以及用于创建该渲染器的接口,该接口可以处理它优雅地失败的情况std::variant或一个std::optional,即:

我的 SDL 渲染器是一个简单的类,带有一个布尔值和一个窗口的 unique_ptr,如下所示:

using SDLWindowUptr = std::unique_ptr<SDL_Window, std::function<void(SDL_Window*)>>;

template <Value, Error>
using either = std::variant<Value, Error>;

enum class SDLRendererError {
    SDLInitFailed, WindowCreationFailed
};

class SDLRenderer {
public:
static either<SDLRenderer, SDLRendererError> createRenderer();

private:
    explicit SDLRenderer(SDLWindowUptr window):
    _isRunning{false},
    _window{std::move(window)} 
    {}

public: // Allow moves, forbid copies
    SDLRenderer(const SDLRenderer& other) = delete;
    SDLRenderer(SDLRenderer&& other) = default;
    SDLRenderer& operator=(const SDLRenderer& other) = delete;
    SDLRenderer& operator=(SDLRenderer&& other) = default;

public:
    int run();
private:
    bool          _isRunning;
    SDLWindowUptr _window;
};

我只是在工厂方法中通过初始化 SDL 来初始化这个类SDL_INIT_VIDEO,然后创建一个 SDL_Window,如果它已成功创建,我将其移入渲染器类:

either<SDLRenderer, SDLRendererError> SDLRenderer::createRenderer() {

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        return SDLRendererError:SDLInitFailed;
    }

    auto windowUptr = SDLWindowUptr{
        SDL_CreateWindow("Title",
                         SDL_WINDOWPOS_CENTERED,
                         SDL_WINDOWPOS_CENTERED,
                         1280, 768,
                         SDL_WINDOW_RESIZABLE),
        SDL_DestroyWindow
    };

    if (!windowUptr) {
         return SDLRendererError::WindowCreationFailed;
    }

    return SDLRenderer{std::move(windowUptr)};
}

而在我的主要:

auto result = SDLRenderer::createRenderer();

if (std::holds_alternative<SDLRenderer>(result) {
    auto& renderer = std::get<SDLRenderer>(result);
    return renderer.run();
}

SDL 初始化成功完成,窗口创建也成功完成。

现在这段代码实际上产生了一个应用程序,其中窗口打开然后立即关闭,并且主循环继续运行(它只是检查SDL_PollEvent,仅此而已),同时SDL_GetError不断喷出相同的错误消息:

活动系统已关闭

这是主循环的代码:

int SDLRenderer::run()
{
    auto event = SDL_Event{};
    _isRunning = true;

    // Main loop
    while(_isRunning) {
        while(SDL_PollEvent(&event)) {
            onEvent(&event);
        }
        std::cout << "[Loop] SDL Error: " << SDL_GetError() << "\n";

        SDL_Delay(200);
    }

    return 0;
}

如果我在过程中不使用变体(或具有完全相同用法的可选),并且在 SDL 端使用完全相同的初始化代码,一切都会运行良好。

关于变体和可选项,或者我的代码在变体/可选中使用时实际上会导致问题,我缺少什么?

标签: c++sdloptionalvariant

解决方案


推荐阅读