Ошибка пользовательского удаления смарт-указателя (unique_ptr) C2027 & C2338 - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь использовать умные указатели с SDL2, и мне нужно пользовательское удаление. Я использую этот код и получаю ошибки C2027 (используя неопределенный тип SDL_Texture) и C2338 (не удается удалить неполный тип)

ftexture = std::make_unique<SDL_Texture>(TTF_RenderText_Solid(font, fontData.c_str(), fontColor),
        [=](SDL_Texture* texture) {SDL_DestroyTexture(texture); });

Эта переменная в моем классе выглядит следующим образом:

std::unique_ptr <SDL_Texture> ftexture = nullptr;

1 Ответ

4 голосов
/ 22 февраля 2020

Во-первых, TTF_RenderText_Solid() возвращает SDL_Surface*, а не SDL_Texture*. SDL_Surface не является производным от SDL_Texture.

Во-вторых, пользовательский указатель удаления нельзя указать с помощью std::make_unique(). Первый аргумент шаблона используется как тип T результирующего std::unique_ptr, а остальные аргументы шаблона используются для входных параметров, которые все передаются конструктору T. В вашем примере T - это SDL_Texture, и нет конструктора SDL_Texture, который бы принимал SDL_Surface* и лямбду в качестве входных данных.

Чтобы использовать пользовательское средство удаления, вам необходимо указать тип средства удаления в качестве аргумента шаблона std::unique_ptr, что std::make_unique() не позволяет вам делать, поэтому вы должны использовать std::unique_ptr напрямую.

Удалитель должен иметь отдельный тип, а не лямбду:

struct SDL_Surface_Deleter
{
    void operator()(SDL_Surface* surface) {
        SDL_FreeSurface(surface);
    } 
};

using SDL_Surface_ptr = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>;
SDL_Surface_ptr fsurface;

...

fsurface = SDL_Surface_ptr(
    TTF_RenderText_Solid(font, fontData.c_str(), fontColor)
);

Но если вы действительно хотите использовать лямбду, вы можете сделать это вместо этого:

using SDL_Surface_Deleter = void (*)(SDL_Surface*);
using SDL_Surface_ptr = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>;
SDL_Surface_ptr fsurface;

...

fsurface = SDL_Surface_ptr(
    TTF_RenderText_Solid(font, fontData.c_str(), fontColor),
    [](SDL_Surface* surface) { SDL_FreeSurface(surface); }
);

Или, вы можете просто использовать SDL_FreeSurface() непосредственно в качестве фактического удалителя:

using SDL_Surface_ptr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
SDL_Surface_ptr fsurface;

...

fsurface = SDL_Surface_ptr(
    TTF_RenderText_Solid(font, fontData.c_str(), fontColor),
    &SDL_FreeSurface
);
...