Использование пользовательского удалителя с std :: shared_ptr

Я пытаюсь понять, как использовать std :: shared_ptr с пользовательским удалением. В частности, я использую его с SDL_Surface как:

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface);

который компилируется и работает нормально. Тем не менее, я хотел бы попробовать свой собственный средство удаления и не могу понять, как это сделать. Документация для SDL_FreeSurface находится здесь:

http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface

в котором я нахожу SDL_FreeSurface объявлен как:

void SDL_FreeSurface(SDL_Surface* surface);

В качестве теста и, следуя этой информации, я попробовал следующую функцию:

void DeleteSurface(SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
}

Тем не менее, компиляция с g ++ дает мне следующую ошибку:

error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)'

Я посмотрел на документацию по gnu для реализации gcc std :: shared_ptr, но не могу понять этого. Что я делаю неправильно?

РЕДАКТИРОВАТЬ: С тех пор я сузил проблему, но оставлю оригинальный вопрос выше. У меня был класс Game, который, если я ограничу его до базовой реализации, представлял собой что-то вроде:

class Game {
public:
/* various functions */
private:
void DeleteSurface(SDL_Surface* surface);
bool CacheImages();
std::vector<std::shared_ptr<SDL_Surface> > mCachedImages;

/* various member variables and other functions */
}

с реализацией DeleteSurface как указано выше, и реализация CacheImages() как:

bool CacheImages()
{
mCachedImages.push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface);
return true;
}

в какой игре мне ошибка я перечислил выше. Тем не менее, если я переместить DeleteSurface() функционировать вне Game Класс, не изменяя его, код компилируется. О чем это в том числе DeleteSurface функция в Game класс, который вызывает проблемы?

34

Решение

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), [=](SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
});

или же

void DeleteSurface(SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
}

std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), DeleteSurface);

РЕДАКТИРОВАТЬ:

Видя ваш обновленный вопрос, DeleteSurface должна быть функцией, не являющейся членом, в противном случае вам нужно использовать std::bind или же std::mem_fn или некоторый другой адаптер указателя на функцию-член.

48

Другие решения

Этот код предоставляет пример построения общего указателя с удалителем в качестве метода объекта. Это отображает std::bind инструкция по использованию.

Примером является простой объект утилизации. Когда последняя ссылка на объект уничтожается, объект возвращается в пул свободных объектов внутри утилизатора.

Recyler может быть легко преобразован в кеш объекта, добавив ключ к get() а также add() методы и путем хранения объектов в std::map,

class ObjRecycler
{
private:
std::vector<Obj*> freeObjPool;
public:
~ObjRecycler()
{
for (auto o: freeObjPool)
delete o;
}

void add(Obj *o)
{
if (o)
freeObjPool.push_back(o);
}

std::shared_ptr<Obj> get()
{
Obj* o;
if (freeObjPool.empty())
o = new Obj();
else
{
o = freeObjPool.back();
freeObjPool.pop_back();
}
return std::shared_ptr<Obj>(o,
std::bind(&ObjRecycler::add, this, std::placeholders::_1));
}
}
10

По вопросам рекламы [email protected]