gpt4 book ai didi

c++ - '': cannot convert from ' initializer list' to 'std::shared_ptr' on creating shared_ptr with custom deleter

转载 作者:行者123 更新时间:2023-11-28 04:18:21 37 4
gpt4 key购买 nike

我为 SDL2 库方法创建了包装仿函数,以返回带有自定义删除器的智能指针。它似乎适用于 unqiue_ptr(类 Image),但对于在构建期间返回 shared_ptr(类 Window)的类给出以下错误:

'<function-style-cast>': cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>'

SDL_CreateWindow这里返回原始 SDL_Window*IMG_Load返回原始 SDL_Surface* .

我试过移动Deleter公开并删除 Window 类的复制限制,但它仍然失败并出现相同的错误。另外,如果我只返回 nullptr从 Window 的函数转换中,它构建得很好。所以问题似乎与 shared_ptr 本身的创建有关。令我感到困惑的是为什么它与 unique_ptr 一起工作得很好但不是 shared_ptr .

#pragma once
#include <memory>
#include <SDL.h>
#include "Uncopyable.h"

// fails during build with error: '<function-style-cast>':
// cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>'
class Window:private Uncopyable {
private:


public:
class Deleter {
void operator()(SDL_Window *window) {
SDL_DestroyWindow(window);
}
};

static const int SCREEN_WIDTH = 800;
static const int SCREEN_HEIGHT = 600;
std::shared_ptr<SDL_Window> operator()() const {
return std::shared_ptr<SDL_Window>(
SDL_CreateWindow("SDL Tutorial",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN),
Deleter());
}
};

#pragma once
#include <memory>
#include <string>
#include <SDL.h>
#include <SDL_image.h>
#include "Uncopyable.h"

// builds fine
class Image: private Uncopyable {
public:
class Deleter{
void operator()(SDL_Surface *image) {
SDL_FreeSurface(image);
}
};

std::unique_ptr<SDL_Surface, Deleter> operator()(const std::string &path) const {
return std::unique_ptr<SDL_Surface, Deleter>(
IMG_Load(path.c_str()),
Deleter());
}
};

预期结果:Window 类应该像 Image 类一样正确构建

实际结果:Window 类失败并出现上述错误,而 Image 类构建良好

更新:通过将 shared_ptr 创建逻辑移动到简单函数来进一步缩小范围,我发现删除自定义 Deleter()删除构建错误。所以它似乎是罪魁祸首。但我需要 Deleter,而且,为什么同样的结构使用 unique_ptr 可以很好地处理 Image。

最佳答案

我已经把你的例子精简了一点:

#include <memory>

// Stub these out since we don't have them available and they don't really matter
// for the substance of the question.
struct SDL_Window {};
void SDL_DestroyWindow( SDL_Window* win ) { delete win; }
SDL_Window* SDL_CreateWindow() { return new SDL_Window{}; }

// fails during build with error: '<function-style-cast>':
// cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>'
class Window {
public:
class Deleter {
void operator()(SDL_Window *window) {
SDL_DestroyWindow(window);
}
};

std::shared_ptr<SDL_Window> operator()() const {
return std::shared_ptr<SDL_Window>(
SDL_CreateWindow(),
Deleter());
}
};

int main()
{
auto win = Window();
auto sp = win();
}

现在问题更明显了:

/usr/local/include/c++/8.2.0/bits/shared_ptr_base.h:642:11: error: 
'void Window::Deleter::operator()(SDL_Window*)' is private within this context
__d(__p); // Call _Deleter on __p.
~~~^~~~~

main.cpp:16:14: note: declared private here
void operator()(SDL_Window *window) {

Coliru 上实时查看它的失败情况.

如果您将 public 添加到您的删除器类或使其成为一个结构,它将起作用。但是,您也可以跳过该类并直接传入删除函数,如果这就是它需要做的所有工作(或者如果它更复杂一点,则使用 lambda):

    std::shared_ptr<SDL_Window> operator()() const {
return std::shared_ptr<SDL_Window>(
SDL_CreateWindow(),
SDL_DestroyWindow);
}

// Or with a lambda if it's more complicated (here also using a factory func)
static std::shared_ptr<SDL_Window> Create() {
return std::shared_ptr<SDL_Window>(
SDL_CreateWindow(),
[] (auto win) {
UnregisterMyWindow( win );
SDL_DestroyWindow( win );
});
}

Coliru 上实时查看它的工作情况.

此外,像那样使用 Window::operator() 是否明智也值得怀疑。我建议您创建一个非成员或静态成员工厂函数来代替创建窗口。

关于c++ - '<function-style-cast >': cannot convert from ' initializer list' to 'std::shared_ptr<SDL_Window>' on creating shared_ptr with custom deleter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56061128/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com