英文:
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<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);
}
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<Window>(std::move(nativeWindow), width, height);
However, it seems you are encapsulating the wrong thing.
- If a 
Windowinstance is copied or moved, there will suddenly be two owners of theGLFWwindow, with a doublefreelater likely. - When a 
Windowis destroyed, you don't callglfwDestroyWindowto 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<GLFWwindow> 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<GLFWwindow, glfwWindowDestroyer> 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<Window>s, you can, but as you will see, it will be rather pointless:
std::unique_ptr<Window>
Window::createWindow(int width, int height, std::string title) {
    return std::make_unique<Window>(width, height, title);
}
There's not much of a gain to call Window::createWindow instead of just calling std::make_unique<Window> directly. Also, the use of unique_ptr<Window>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<Window>(std::move(nativeWindow), width, height);
However, it seems you are encapsulating the wrong thing.
- If a 
Windowinstance is copied or moved, there will suddenly be two owners of theGLFWwindow, with a doublefreelater likely. - When a 
Windowis destroyed, you don't callglfwDestroyWindowto 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<GLFWwindow> 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<GLFWwindow, glfwWindowDestroyer> 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<Window>s, you can, but as you will see, it will be rather pointless:
std::unique_ptr<Window>
Window::createWindow(int width, int height, std::string title) {
    return std::make_unique<Window>(width, height, title);
}
There's not much of a gain to call Window::createWindow instead of just calling std::make_unique<Window> directly. Also, the use of unique_ptr<Window>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<Window>(std::move(nativeWindow), width, height);
假设你的 Window 类型有以下可用的构造函数:
Window::Window(GLFWwindow* win, int width, int height)
可以通过添加正确的构造函数来解决这个问题(我还传递了标题,你没有存储它)。
Window.hpp
#pragma once
#include <memory>
#include <string>
#include <GLFW/glfw3.h>
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<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;
};
#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>(nativeWindow, width, height, title);
}
然后,你应该这样调用这个方法:
std::unique_ptr<Window> ptr = Window::createWindow(640, 480, "hello") 
<details>
<summary>英文:</summary>
This line:
```c++
std::make_unique<Window>(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 <memory>
#include <string>
#include <GLFW/glfw3.h>
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<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;
};
#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>(nativeWindow, width, height, title);
}
Then you should be call the method like so:
std::unique_ptr<Window> ptr = Window::createWindow(640, 480, "hello") 
				通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论