“<function-style-cast>”:在使用自定义删除器创建 shared_ptr 时无法从 'initializer list' 转换为 'std::shared_ptr<SDL_Window>'
'<function-style-cast>': cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>' on creating shared_ptr with custom deleter
我为带有自定义删除器的 return 智能指针的 SDL2 库方法创建了包装仿函数。它似乎适用于 unqiue_ptr (class Image) 但对于 classes returning shared_ptr (class Window) 构建期间:
'<function-style-cast>': cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>'
这里的 SDL_CreateWindow
return 是原始的 SDL_Window*
和 IMG_Load
return 是原始的 SDL_Surface*
。
我已经尝试将 Deleter
移动到 public 并删除 Window class 的复制限制,但仍然失败并出现相同的错误。另外,如果我只是 return 来自 Window 的函数转换的 nullptr
,那么它构建得很好。所以问题似乎与 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 class 应该像图像 class
一样构建而不会出现错误
实际结果:Window class 失败并出现上述错误,而图像 class 构建良好
更新:通过将 shared_ptr 创建逻辑移动到简单函数来进一步缩小范围,我发现删除自定义 Deleter()
会消除构建错误。所以它似乎是罪魁祸首。但是我需要 Deleter 以及为什么相同的结构可以很好地处理使用 unique_ptr 的图像。
我已将您的示例精简了一点:
#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
添加到您的删除器 class 或使其成为一个结构,它将起作用。但是,您也可以跳过 class 并直接传入删除函数,如果这就是它需要做的所有工作(或者如果它更复杂一点,则使用 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()
是否明智。我建议您制作一个 non-member 或静态成员工厂函数,而不是制作 windows.
我为带有自定义删除器的 return 智能指针的 SDL2 库方法创建了包装仿函数。它似乎适用于 unqiue_ptr (class Image) 但对于 classes returning shared_ptr (class Window) 构建期间:
'<function-style-cast>': cannot convert from 'initializer list' to 'std::shared_ptr<SDL_Window>'
这里的 SDL_CreateWindow
return 是原始的 SDL_Window*
和 IMG_Load
return 是原始的 SDL_Surface*
。
我已经尝试将 Deleter
移动到 public 并删除 Window class 的复制限制,但仍然失败并出现相同的错误。另外,如果我只是 return 来自 Window 的函数转换的 nullptr
,那么它构建得很好。所以问题似乎与 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 class 应该像图像 class
一样构建而不会出现错误实际结果:Window class 失败并出现上述错误,而图像 class 构建良好
更新:通过将 shared_ptr 创建逻辑移动到简单函数来进一步缩小范围,我发现删除自定义 Deleter()
会消除构建错误。所以它似乎是罪魁祸首。但是我需要 Deleter 以及为什么相同的结构可以很好地处理使用 unique_ptr 的图像。
我已将您的示例精简了一点:
#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
添加到您的删除器 class 或使其成为一个结构,它将起作用。但是,您也可以跳过 class 并直接传入删除函数,如果这就是它需要做的所有工作(或者如果它更复杂一点,则使用 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()
是否明智。我建议您制作一个 non-member 或静态成员工厂函数,而不是制作 windows.