J'essaie de savoir comment utiliser std :: shared_ptr avec un suppresseur personnalisé. Plus précisément, je l'utilise avec SDL_Surface en tant que:
std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface);
qui compile et fonctionne bien. Cependant, je voudrais essayer mon propre délétère et je ne peux pas trouver comment le faire. La documentation de SDL_FreeSurface se trouve ici:
http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface
dans lequel je trouve que la SDL_FreeSurface est déclarée comme:
void SDL_FreeSurface(SDL_Surface* surface);
À titre de test, et en fonction de ces informations, j'ai essayé la fonction suivante:
void DeleteSurface(SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
}
Cependant, la compilation avec g ++ me donne l'erreur suivante:
error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)'
J'ai regardé la documentation gnu pour l'implémentation de gcc std :: shared_ptr mais je ne peux pas lui donner beaucoup de sens. Qu'est-ce que je fais mal?
EDIT: J'ai depuis réduit le problème, mais je vais laisser la question d'origine ci-dessus. Ce que j'avais était une classe de jeu qui, si je la déduisais d'une implémentation de base, ressemblait à:
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 */
}
avec l'implémentation de DeleteSurface
comme ci-dessus, et l'implémentation de CacheImages()
comme:
bool CacheImages()
{
mCachedImages.Push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface);
return true;
}
quel jeu me l'erreur que j'ai énumérée ci-dessus. Cependant, si je déplace la fonction DeleteSurface()
en dehors de la classe Game
sans la modifier autrement, le code se compile. En quoi consiste l'inclusion de la fonction DeleteSurface
dans la classe Game
qui pose problème?
std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), [=](SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
});
ou
void DeleteSurface(SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
}
std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....), DeleteSurface);
MODIFIER:
En voyant votre question mise à jour, DeleteSurface
devrait être une fonction non membre, sinon vous devez utiliser std::bind
ou std::mem_fn
ou un autre adaptateur de pointeur de fonction membre.
Ce code fournit un exemple de construction de pointeur partagé avec le suppresseur comme méthode d'objet. Il affiche l'instruction std::bind
À utiliser.
L'exemple est un simple recycleur d'objets. Lorsque la dernière référence à l'objet est détruite, l'objet est renvoyé au pool d'objets libres à l'intérieur du recycleur.
Le recyler peut être facilement transformé en cache d'objets en ajoutant une clé aux méthodes get()
et add()
et en stockant les objets dans un 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));
}
}