'<function-style-cast>':<SDL_Window>使用自定义删除程序创建shared_ptr时无法从"初始值设定项列表"转换为"std::shared



i创建了用于SDL2库方法的包装函数,以返回使用自定义删除器的智能指针。对于unqiue_ptr(类图像(,它似乎可以正常工作,但是在构建过程中返回共享_ptr(类窗口(的类以下错误:

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

SDL_CreateWindow这里返回RAW SDL_Window*IMG_Load返回RAW SDL_Surface*

我已经尝试将Deleter移至公共场所并删除窗口类的复制限制,但仍会出现同样的错误。另外,如果我只是从Window的功能铸件中返回nullptr,则可以构建正常。因此,问题似乎是在共享_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());
    }
};

预期结果:窗口类应不会像图像类

那样构建窗口类别

实际结果:窗口类失败,上面给出的错误,而图像类则构建良好

更新:通过将共享_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添加到Deleter类或使其成为结构,则它将起作用。但是,如果这是需要做的所有工作,您也可以跳过该类,然后直接通过删除功能(或者如果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()是可疑的智慧。我建议您制作非成员或静态成员出厂功能以制作Windows。

相关内容

最新更新