Не могу вернуть nullptr для типа возвращаемого значения unique_ptr - PullRequest
7 голосов
/ 09 мая 2019

Я пишу оболочку для SDL_Texture* необработанного указателя, который возвращает unique_ptr.

using TexturePtr = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>;

TexturePtr loadTexture(SDL_Renderer* renderer, const std::string &path) {
    ImagePtr surface =
        loadImage(path);
    if (surface) {
        return TexturePtr(
            SDL_CreateTextureFromSurface(renderer, surface.get())
            , SDL_DestroyTexture);
    }
    return nullptr;
}

Но выдает следующую ошибку:

no suitable constructor exists to convert from "std::nullptr_t" to "std::unique_ptr<SDL_Texture, void (__cdecl *)(SDL_Texture *texture)>"

Насколько я понимаю, допустимо передавать nullptr вместо unique_ptr. Я попытался передать пустой unique_ptr при последнем возврате:

return TexturePtr();

но вы получите похожую ошибку во время сборки.

Пожалуйста, дайте мне знать, что я здесь делаю неправильно.

ENV: компилятор: Visual C ++ 14.1

Ответы [ 2 ]

8 голосов
/ 09 мая 2019

Конструктор unique_ptr(nullptr_t) требует, чтобы удаляемый объект был конструируемым по умолчанию и чтобы он не был указателем типа.Ваш удалитель не удовлетворяет второму условию, потому что удалитель является указателем на функцию.См. [unique.ptr.single.ctor] / 1 и [unique.ptr.single.ctor] / 4 .

Это ограничение хорошо, потому чтоКонструкция по умолчанию для вашего средства удаления приводит к nullptr и неопределенному поведению, что, вероятно, приводит к segfault при попытке вызвать средство удаления.

Вы можете изменить свой оператор возврата на

return TexturePtr{nullptr, SDL_DestroyTexture};  // or just {nullptr, SDL_DestroyTexture}

В качестве альтернативы предоставьте средство удаления, которое удовлетворяет вышеуказанным требованиям.Один такой вариант показан в другом ответе, который я написал здесь .

0 голосов
/ 09 мая 2019

РЕДАКТИРОВАТЬ: На самом деле мой пример, приведенный ниже, слишком упрощен, подсказка Pratorian об удалителе, вероятно, является подсказкой к вашей проблеме.msvc - см. https://godbolt.org/z/CU4tn6 для вывода компилятора

#include <memory>

std::unique_ptr<int> f() {
    return nullptr;
}

Вы можете попробовать различные варианты, такие как

#include <memory>

std::unique_ptr<int> f() {
    return {};
}

, но в противном случае, я думаю, у вас нет выбора, кроме как обновить свойкомпилятор.

...