我目前正在尝试使用glfw在 C++ 中编写一个小型引擎来创建窗口。我想充分利用 raii 来提出一个异常安全的架构,并使引擎几乎不可能以错误的方式使用。但我目前正在努力解决一些问题,我觉得我错过了一些重要的东西,所以我在这里问,提前谢谢大家!
假设我有一个raii
名为的基本结构,它在和中glfw_context
调用。它也接受一个并在调用之前设置它,但我会省略这些细节,因为我想专注于基本问题。我还创建了一个类,它需要 a在wheras 中采用相同类型的参数但带有 a is的重载。glfwInit()
ctor
glfwTerminate()
dtor
error-callback
glfwInit()
glfw_window
const glfw_context&
ctor
ctor
glfw_context&&
deleted
这背后的想法是,当上下文是时,rvalue
它只会在ctor
调用期间存在,但glfwTerminate()
会在所有窗口被正确销毁之前被调用(这发生在dtor
类中glfw_window
)。我moves
正确实现了,glfw_window
而glfw_context
不能复制或移动。但问题从这里开始:我无法阻止用户创建多个glfw_context
实例。所以我static
现在和一个成员一起去了,因为glfw没有公开像glfwIsInit()这样的东西,它在我的框架范围内解决了这个问题(只有最旧的实例会调用glfwTerminate()
),但这仍然不能保护用户免于编写这样的代码:
std::vector< glfw_window > windows;
{
// introduce explicit scope to demonstrate the problem
glfw_context context{};
windows.emplace_back( context, ... );
}
在这种情况下,上下文仍然不会超过窗口。
有解决这个问题的好方法吗?我不想把它作为要求放在文档中(像“上下文必须比每个窗口都活得久”之类的东西似乎对我来说并不适用)。
我目前的方法是使用 astd::shared_pointer< glfw_context >
作为glfw_window
's的参数ctor
并将其存储为成员。但是,这仍然不能解决我的问题,因为我仍然可以make_shared< glfw_context >()
使用不同的上下文并将它们传递给不同的窗口。并且由于只有第一个分配的实例会调用glfwTerminate()
我仍然可以引发上下文在所有窗口之前被破坏的情况。
那么解决这类问题的正确方法是什么?无论用户如何尝试(错误)使用它,我能否构建一个在这里正常工作的漂亮架构?我的其他一些想法包括一个private ctor
inglfw_context
和一个static
工厂方法与 - 方法相结合,shared_pointer
但这感觉很像一个singleton
,我怀疑这是处理事情的最佳方式。