Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

functor template.

6 réponses
Avatar
Stephane Wirtel
Bonjour,

Bonne année à tous et mes meilleurs voeux à tous.

Voici un petit problème concernant la libération de mémoire occupée par des pointeurs dans des conteneurs.

Pour vider mes container, je m'amuse avec std::for_each (it.begin (), it.end (), Delete ());

La structure Delete correspond au code suivant :
struct Delete {
template <typename T> void operator () (T *ptr) {
if (0 != ptr) {
delete ptr;
ptr = 0;
}
}
};

Le problème avec ce functor template, est qu'il ne prendra pas des items d'une collection assiociative style std::map.

Donc j'ai pensé à faire une spécialisation comme l'exemple donné par après, mais je ne pense vraiment pas que cela puisse fonctionner.

struct Delete {
template <typename T> void operator () (T *ptr) {
if (0 != ptr) {
delete ptr;
ptr = 0;
}
}

template <> void operator () <std::pair <const std::string &, T *> > (std::pair <const std::string &, T*> &pData) {
if (0 != pData.second) {
delete pData.second;
pData.second = 0;
}
}
};

Pensez-vous que cela soit possible ?
Et comment auriez-vous fait pour supprimer un élément d'un conteneur associatif ?

Bien à vous,

Stéphane

6 réponses

Avatar
Stephane Wirtel
Bonjour,

Vous pouvez arrêter de chercher, j'ai trouvé une solution qui semble répondre à mes problèmes.

Mais j'aurais tout de même voulu avoir votre opinion sur la manière de faire quelque chose de propre.

Stef
Avatar
Youssef Mesri
Stephane Wirtel wrote:
Bonjour,

Vous pouvez arrêter de chercher, j'ai trouvé une solution qui semble
répondre à mes problèmes.

Mais j'aurais tout de même voulu avoir votre opinion sur la manière de
faire quelque chose de propre.

Stef


tu peux essayer cela:

template<typename T>
void better_delete(T*& ptr) {
delete ptr;
ptr = 0;
}

yous

Avatar
Stephane Wirtel
Youssef Mesri wrote:
Stephane Wirtel wrote:
Bonjour,

Vous pouvez arrêter de chercher, j'ai trouvé une solution qui semble
répondre à mes problèmes.

Mais j'aurais tout de même voulu avoir votre opinion sur la manière de
faire quelque chose de propre.

Stef


tu peux essayer cela:

template<typename T>
void better_delete(T*& ptr) {
delete ptr;
ptr = 0;
}
Pour un conteneur non-associatif (std::vector, std::list, ...) ça peut fonctionner,

mais pour un associatif, comment feras-tu ?

Stef


Avatar
kanze
Stephane Wirtel wrote:

Voici un petit problème concernant la libération de mémoire
occupée par des pointeurs dans des conteneurs.

Pour vider mes container, je m'amuse avec std::for_each
(it.begin (), it.end (), Delete ());

La structure Delete correspond au code suivant :
struct Delete {
template <typename T> void operator () (T *ptr) {
if (0 != ptr) {
delete ptr;
ptr = 0;
}
}
};


Pourquoi le test ? delete sur un pointeur nul est bien défini.

Ce que je fais d'habitude, c'est quelque chose du genre :

while ( ! c.empty() ) {
T* tmp = c.back() ;
c.pop_back() ;
delete tmp ;
}

Si le but d'est de laisser les pointeurs nuls dans le
collection, j'utilise :

struct Deleter
{
template< typename T >
void operator()( T*& ptr )
{
T* tmp = null ;
std::swap( ptr, tmp ) ;
delete tmp ;
}
} ;

Le problème avec ce functor template, est qu'il ne prendra pas
des items d'une collection assiociative style std::map.


C'est parce que tout compte fait, std::map n'est pas réelement
une collection ; pour le faire passer au modèle, on l'a tordu,
en lui donnant un value_type spécial, qui n'est pas un pointeur
(et qui ne peut pas être défini par l'utilisateur).

J'imagine qu'il y a des trucs à faire avec un surcharge de
l'operator() ci-dessus, puis de la métaprogrammation pour faire
le delete si first ou second est un pointeur, et non s'il ne
l'est pas, mais j'avoue que je ne vois pas l'intérêt ; je crois
que je n'ai jamais eu un std::map qui était propriétaire des
pointeurs qu'il contenait.

Donc j'ai pensé à faire une spécialisation comme l'exemple
donné par après, mais je ne pense vraiment pas que cela puisse
fonctionner.

struct Delete {
template <typename T> void operator () (T *ptr) {
if (0 != ptr) {
delete ptr;
ptr = 0;
}
}

template <> void operator () <std::pair <const std::string &, T *> > (st d::pair <const std::string &, T*> &pData) {
if (0 != pData.second) {
delete pData.second;
pData.second = 0;
}
}
};


Il s'agit d'une fonction, non d'une classe. Il n'y a donc pas de
spécialisation partielle, mais du surcharge. Quelque chose du
genre :

struct Delete
{
template< typename T > void operator()( T*& ptr ) ;
template< typename T1, typename T2 >
void operator()( std::pair< T1, T2 >& elem ) ;
} ;

Pensez-vous que cela soit possible ?


Je ne sais pas. Je n'ai jamais compris les règles qui concerne
quand un type est « déduisible », et quand non. Mais a priori,
pourquoi pas. Ensuite, il faut utiliser des techniques de
métaprogrammation comme on trouve en Boost pour faire le delete
sur le first ou le second, selon ce qu'ils soient pointeurs ou
non.

Et comment auriez-vous fait pour supprimer un élément d'un
conteneur associatif ?


Pour supprimer l'élément, j'utilise erase, tout court.

En ce qui concerne les objets éventuellement pointés par
l'élément, je n'ai pas de solution générale, parce que
jusqu'ici, le problème varie avec l'utilisation : d'abord, c'est
extrèmement rare que le map est propriétaire ; ensuite,
j'imagine que c'est parfois le first, parfois le second et
parfois les deux dont il faut faire delete.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Alexandre
"Stephane Wirtel" a écrit dans le message de
news: dpdt5n$bq7$
Bonjour,

Vous pouvez arrêter de chercher, j'ai trouvé une solution qui semble
répondre à mes problèmes.

Mais j'aurais tout de même voulu avoir votre opinion sur la manière de
faire quelque chose de propre.



personnelement je ne mets pas de pointeurs dans une collection, mais des
"pointeurs intelligents" partagés (j'ai écrit un shared_ptr mais il y en a
chez boost qui conviennent) car std::auto_ptr ne convient pas aux conteneurs
STL. Du coup, le destructeur du conteneur appellant le destructeur de chaque
objet, et tu n'as pas à te soucier de le faire, que ce soit pour une map ou
un vector...

Avatar
Stephane Wirtel
personnelement je ne mets pas de pointeurs dans une collection, mais des
"pointeurs intelligents" partagés (j'ai écrit un shared_ptr mais il y en a
chez boost qui conviennent) car std::auto_ptr ne convient pas aux conteneurs
STL. Du coup, le destructeur du conteneur appellant le destructeur de chaque
objet, et tu n'as pas à te soucier de le faire, que ce soit pour une map ou
un vector...


Merci de l'idée des shared_ptr,


Stef