Я пытаюсь понять, как использовать 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
класс, который вызывает проблемы?
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
или некоторый другой адаптер указателя на функцию-член.
Этот код предоставляет пример построения общего указателя с удалителем в качестве метода объекта. Это отображает 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));
}
}