Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用c++;和glfw 我目前正试图在C++中编写一个小引擎,用于窗口创建。我想充分利用raii来设计一个异常安全的架构,使引擎实际上不可能以错误的方式使用。 但是我现在遇到了一些问题,我觉得我错过了一些重要的东西,所以我在这里问,提前谢谢大家_C++_Glfw_Raii_Exception Safety_C++17 - Fatal编程技术网

使用c++;和glfw 我目前正试图在C++中编写一个小引擎,用于窗口创建。我想充分利用raii来设计一个异常安全的架构,使引擎实际上不可能以错误的方式使用。 但是我现在遇到了一些问题,我觉得我错过了一些重要的东西,所以我在这里问,提前谢谢大家

使用c++;和glfw 我目前正试图在C++中编写一个小引擎,用于窗口创建。我想充分利用raii来设计一个异常安全的架构,使引擎实际上不可能以错误的方式使用。 但是我现在遇到了一些问题,我觉得我错过了一些重要的东西,所以我在这里问,提前谢谢大家,c++,glfw,raii,exception-safety,c++17,C++,Glfw,Raii,Exception Safety,C++17,假设我有一个名为glfw_context的基本raii-struct,它在ctor中调用glfwInit(),在dtor中调用glfwetermint()。它还接受一个错误回调,并在调用glfwInit()之前对其进行设置,但我将省略这些细节,因为我想把重点放在基本问题上。 我还创建了一个类glfw_窗口,当重载的ctor采用相同类型的参数但带有glfw_上下文&&被删除时,它需要ctor中的常量glfw_上下文& 这背后的想法是,当上下文是一个rvalue时,它只会在ctor调用期间存在,但是

假设我有一个名为
glfw_context
的基本
raii
-struct,它在
ctor
中调用
glfwInit()
,在
dtor
中调用
glfwetermint()
。它还接受一个
错误回调
,并在调用
glfwInit()
之前对其进行设置,但我将省略这些细节,因为我想把重点放在基本问题上。 我还创建了一个类
glfw_窗口
,当重载的
ctor
采用相同类型的参数但带有
glfw_上下文&&
被删除时,它需要
ctor
中的
常量glfw_上下文&

这背后的想法是,当上下文是一个
rvalue
时,它只会在
ctor
调用期间存在,但是
glfwderminate()
会在所有窗口被正确销毁之前被调用(这发生在
glfw\u窗口
类的
dtor
中)。 我为
glfw_窗口
正确执行了
moves
,而
glfw_上下文
既不能复制也不能移动。但问题从这里开始: 我无法阻止用户创建多个
glfw_context
实例。因此,我现在使用了一个
静态
成员,因为它没有公开这样的东西,在我的框架范围内解决了这个问题(只有最旧的实例会调用
glfweterminate()
),但这仍然不能保护用户编写这样的代码:

std::vector< glfw_window > windows;
{
    // introduce explicit scope to demonstrate the problem
    glfw_context context{};
    windows.emplace_back( context, ... );
}
std::vectorwindows;
{
//引入显式范围来演示问题
glfw_上下文{};
windows.emplace_back(上下文,…);
}
在这种情况下,上下文仍然不会超过窗口

有什么好办法解决这个问题吗?我不想把它作为一项要求放在文档中(像“上下文必须比每个窗口都长”这样的东西似乎对我来说并不合适)

我目前的方法是使用
std::shared_指针
作为
glfw_窗口的
ctor
的参数,并将其存储为成员。然而,这仍然不能解决我的问题,因为我仍然可以
使_共享()
不同的上下文,并将它们传递到不同的窗口。由于只有第一个分配的实例会调用
glfwTerminate()
,因此我仍然可以证明上下文在所有窗口之前被破坏的情况

那么,解决这类问题的正确方法是什么?无论用户如何尝试(错误地)使用它,我是否可以在这里构建一个良好的体系结构并正常工作?
我的一些其他想法包括
glfw_context
中的
私有ctor
静态
工厂方法与
共享指针
-方法相结合,但这感觉很像
单例
,我怀疑这是处理问题的最佳方式。

您可能会使用单例的一种变体:

class glfw_context
{
    glfw_context() {/*Your impl*/}

    glfw_context(const glfw_context&) = delete;
    glfw_context& operator=(const glfw_context&) = delete;
public:
    friend std::shared_ptr<glfw_context> CreateContext()
    {
        static std::weak_ptr<glfw_context> instance;

        auto res = instance.lock();
        if (res == nullptr) {
            res = std::make_shared<glfw_context>();
            instance = res;
        }
        return res;
    }

    /* Your impl */
};
类glfw_上下文
{
glfw_context(){/*您的impl*/}
glfw_上下文(const glfw_context&)=删除;
glfw_上下文&运算符=(常量glfw_上下文&)=删除;
公众:
friend std::shared_ptr CreateContext()
{
静态std::弱_ptr实例;
auto res=instance.lock();
如果(res==nullptr){
res=std::使_共享();
实例=res;
}
返回res;
}
/*你的建议*/
};
然后,只要至少有一个“引用”到您的实例,
CreateContext()
就会返回它,否则它会创建一个新的引用。

不可能有两个不同的
glfw\u context

实例使构造函数私有,并创建一个返回现有共享\u ptr的工厂或创建一个工厂。但是如果该
共享\u ptr
是静态的,它将如何被删除?当然,我可以在对
glfw_context::get_context()
的第一次调用中创建它,并将其存储在
glfw_窗口
实例中,这样
glfw_context
将比它更长寿,但该静态成员仍然会持有一个引用,对吗?那它的一生呢?谢谢@jarod42!能否请您澄清,将
实例
作为
类的
静态
成员或
CreateContext()的
静态
成员之间是否有区别?我是否可以将实现和
静态实例
隐藏在.cpp/.cc文件中,或者这会产生一些问题?谢谢你的解决方案-虽然我没有足够的代表来支持它。你可以将
CreateContext
的定义放在cpp文件中(但它仍然应该是
friend
(或静态方法),以便能够调用构造函数)。在
static
成员和
static
内部方法之间有细微的区别。例如,当它第一次初始化时。对于您的情况,我希望这两种方法都是可行的(您不会在
main
之前调用
CreateContext
)。对,这些调用只会发生在main中,所以这种方法会起作用。关于代码的最后一个问题是:
CreateContext()
是否打算成为
private
而不是
static
?它应该叫什么名字?我想我最常用的方法是使用名为
CreateContext()
public static
成员函数,所有细节都隐藏在cc文件中。当然,一个免费的
friend
功能也会像你建议的那样工作,如果你能详细说明与mayb相比的后果,我将非常感激