C2661 在使用 std::make_unique 时发生

huangapple go评论73阅读模式
英文:

C2661 when using std::make_unique

问题

在尝试使用std::make_unique时出现了错误。如果有人能指出我可能犯了一个非常简单的错误,我将不胜感激。我正在使用GLAD和GLFW作为第三方库。当我运行它时,我得到了一个错误代码C2661,错误消息是“'Window::Window':没有接受3个参数的重载函数”,出现在window.cpp中的以下代码片段:

return std::make_unique<Window>(std::move(nativeWindow), width, height);
Window.hpp
#pragma once

#include <memory>
#include <string>

#include <GLFW/glfw3.h>

struct Window final {
public:
    std::unique_ptr<Window> createWindow(int width, int height, std::string title);

    bool shouldClose() { return glfwWindowShouldClose(nativeWindow); }

    void swapBuffers() { glfwSwapBuffers(nativeWindow); }
private:
    GLFWwindow* nativeWindow;
    int width;
    int height;
    std::string title;
};

Window.cpp
#include "Window.hpp"

std::unique_ptr<Window> Window::createWindow(int width, int height, std::string title) {
    nativeWindow = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
    glfwMakeContextCurrent(nativeWindow);

    return std::make_unique<Window>(std::move(nativeWindow), width, height);
}

对于翻译,请注意:

  • std::make_unique是C++中用于创建std::unique_ptr对象的函数,它的参数是要包装的对象类型及其构造函数的参数。

  • 错误代码C2661表明在调用std::make_unique时,找不到匹配的构造函数来接受给定的参数。可能是因为构造函数的签名不匹配或构造函数未正确定义。

  • 代码中的std::make_unique<Window>(std::move(nativeWindow), width, height)尝试创建一个Window对象的std::unique_ptr,但是似乎Window类没有一个接受这三个参数的构造函数。

希望这个信息对你有所帮助,以解决你的问题。

英文:

I have an error when I am trying to use std::make_unique. I probably have made a very simple mistake and I would be thankful if someone pointed it out. I am using GLAD and GLFW as 3rd party libraries. I get an error code of C2661 when I run it, C2661 'Window::Window': no overloaded function takes 3 arguments on the next code snippet in window.cpp.

return std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);
Window.hpp
#pragma once

#include &lt;memory&gt;
#include &lt;string&gt;

#include &lt;GLFW/glfw3.h&gt;

struct Window final {
public:
	std::unique_ptr&lt;Window&gt; createWindow(int width, int height, std::string title);

	bool shouldClose() { return glfwWindowShouldClose(nativeWindow); }

	void swapBuffers() { glfwSwapBuffers(nativeWindow); }
private:
	GLFWwindow* nativeWindow;
	int width;
	int height;
	std::string title;
};

Window.cpp
#include &quot;Window.hpp&quot;

std::unique_ptr&lt;Window&gt; Window::createWindow(int width, int height, std::string title) {
	nativeWindow = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
	glfwMakeContextCurrent(nativeWindow);

	return std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);
}

sorry for bad code quality.

答案1

得分: 6

Your Window class does not have a constructor taking GLFWwindow*, int, int as would be required for this:

return std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);

However, it seems you are encapsulating the wrong thing.

  • If a Window instance is copied or moved, there will suddenly be two owners of the GLFWwindow, with a double free later likely.
  • When a Window is destroyed, you don't call glfwDestroyWindow to free the resource, which will leak.

Read The rule of 3/5/0.

What you should be doing is really to store a unique_ptr&lt;GLFWwindow&gt; in Window to make the problems mentioned above go away without having to implement the manual resource management mentioned in The rule of 3/5/0.

Example:

struct Window final {
public:
    Window(int width, int height, std::string title);

    inline bool shouldClose() { return glfwWindowShouldClose(nativeWindow.get()); }
    inline void swapBuffers() { glfwSwapBuffers(nativeWindow.get()); }

private:
    struct glfwWindowDestroyer {
        void operator()(GLFWwindow* win) const {
            glfwDestroyWindow(win);
        }
    };
    std::unique_ptr&lt;GLFWwindow, glfwWindowDestroyer&gt; nativeWindow;
    int width;
    int height;
    std::string title;
};

The constructor implementation would then be:

Window::Window(int width, int height, std::string title) :
    nativeWindow(glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr)),
    width(width),
    height(height),
    title(std::move(title))
{
    glfwMakeContextCurrent(nativeWindow.get());
}

That way the createWindow function (which should have been static) can be removed. Just create Windows like normal C++ objects. Window objects are now safely moveable (and non-copyable) without any extra tinkering.


If you for some reason still would like to have a helper function to create unique_ptr&lt;Window&gt;s, you can, but as you will see, it will be rather pointless:

std::unique_ptr&lt;Window&gt;
Window::createWindow(int width, int height, std::string title) {
    return std::make_unique&lt;Window&gt;(width, height, title);
}

There's not much of a gain to call Window::createWindow instead of just calling std::make_unique&lt;Window&gt; directly. Also, the use of unique_ptr&lt;Window&gt;s is dubious. Window is final and it's not inheriting from anything. You should probably just store Windows directly in a container.

英文:

Your Window class does not have a constructor taking GLFWwindow*, int, int as would be required for this:

return std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);

However, it seems you are encapsulating the wrong thing.

  • If a Window instance is copied or moved, there will suddenly be two owners of the GLFWwindow, with a double free later likely.
  • When a Window is destroyed, you don't call glfwDestroyWindow to free the resource, which will leak.

Read The rule of 3/5/0.

What you should be doing is really to store a unique_ptr&lt;GLFWwindow&gt; in Window to make the problems mentioned above go away without having to implement the manual resource management mentioned in The rule of 3/5/0.

Example:

struct Window final {
public:
    Window(int width, int height, std::string title);

    inline bool shouldClose() { return glfwWindowShouldClose(nativeWindow.get()); }
    inline void swapBuffers() { glfwSwapBuffers(nativeWindow.get()); }

private:
    struct glfwWindowDestroyer {
        void operator()(GLFWwindow* win) const {
            glfwDestroyWindow(win);
        }
    };
    std::unique_ptr&lt;GLFWwindow, glfwWindowDestroyer&gt; nativeWindow;
    int width;
    int height;
    std::string title;
};

The constructor implementation would then be:

Window::Window(int width, int height, std::string title) :
    nativeWindow(glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr)),
    width(width),
    height(height),
    title(std::move(title))
{
    glfwMakeContextCurrent(nativeWindow.get());
}

That way the createWindow function (which should have been static) can be removed. Just create Windows like normal C++ objects. Window objects are now safely moveable (and non-copyable) without any extra tinkering.


If you for some reason still would like to have a helper function to create unique_ptr&lt;Window&gt;s, you can, but as you will see, it will be rather pointless:

std::unique_ptr&lt;Window&gt;
Window::createWindow(int width, int height, std::string title) {
    return std::make_unique&lt;Window&gt;(width, height, title);
}

There's not much of a gain to call Window::createWindow instead of just calling std::make_unique&lt;Window&gt; directly. Also, the use of unique_ptr&lt;Window&gt;s is dubious. Window is final and it's not inheriting from anything. You should probably just store Windows directly in a container.

答案2

得分: 0

这行:
```c++
std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);

假设你的 Window 类型有以下可用的构造函数:

Window::Window(GLFWwindow* win, int width, int height)

可以通过添加正确的构造函数来解决这个问题(我还传递了标题,你没有存储它)。

Window.hpp

#pragma once

#include &lt;memory&gt;
#include &lt;string&gt;

#include &lt;GLFW/glfw3.h&gt;

struct Window final {
public:

    // Window 对象的构造函数
    Window(GLFWwindow* win, int w, int h, std::string title) 
       : nativeWindow(win), width(w), height(h), title(title)
    {
    }

    // 我假设你希望这个方法是静态的?
    // 作为成员函数几乎没有多大意义。
    static 
    std::unique_ptr&lt;Window&gt; createWindow(int width, int height, std::string title);

    bool shouldClose() { return glfwWindowShouldClose(nativeWindow); }

    void swapBuffers() { glfwSwapBuffers(nativeWindow); }
   


private:
    GLFWwindow* nativeWindow;
    int width;
    int height;
    std::string title;
};
#include &quot;Window.hpp&quot;

std::unique_ptr&lt;Window&gt; Window::createWindow(int width, int height, std::string title) {
    nativeWindow = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
    glfwMakeContextCurrent(nativeWindow);

    return std::make_unique&lt;Window&gt;(nativeWindow, width, height, title);
}

然后,你应该这样调用这个方法:

std::unique_ptr&lt;Window&gt; ptr = Window::createWindow(640, 480, &quot;hello&quot;) 

<details>
<summary>英文:</summary>

This line:
```c++
std::make_unique&lt;Window&gt;(std::move(nativeWindow), width, height);

assumes your Window type has the following constructor available:

Window::Window(GLFWwindow* win, int width, int height)

This can be fixed by adding the correct constructor (I've also passed through the title, which you weren't storing anywhere).

Window.hpp

#pragma once

#include &lt;memory&gt;
#include &lt;string&gt;

#include &lt;GLFW/glfw3.h&gt;

struct Window final {
public:


    // constructor for Window object
    Window(GLFWwindow* win, int w, int h, std::string title) 
       : nativeWindow(win), width(w), height(h), title(title)
    {
    }

    // I assume you meant for this method to be static?
    // It makes very little (if any sense) as a member function.
    static 
    std::unique_ptr&lt;Window&gt; createWindow(int width, int height, std::string title);

    bool shouldClose() { return glfwWindowShouldClose(nativeWindow); }

    void swapBuffers() { glfwSwapBuffers(nativeWindow); }
   


private:
    GLFWwindow* nativeWindow;
    int width;
    int height;
    std::string title;
};
#include &quot;Window.hpp&quot;

std::unique_ptr&lt;Window&gt; Window::createWindow(int width, int height, std::string title) {
    nativeWindow = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
    glfwMakeContextCurrent(nativeWindow);

    return std::make_unique&lt;Window&gt;(nativeWindow, width, height, title);
}

Then you should be call the method like so:

std::unique_ptr&lt;Window&gt; ptr = Window::createWindow(640, 480, &quot;hello&quot;) 

huangapple
  • 本文由 发表于 2023年7月11日 11:00:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658462.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定