OVH Cloud OVH Cloud

Héritage de std::auto_ptr.

8 réponses
Avatar
Stephane Wirtel
Bonsoir,

Dans le code suivant, j'essaie par héritage d'utiliser std::auto_ptr
afin de donner la possibilité de libérer la mémoire occupée par les
nodes qui composent une std::list (dans ce cas présent, mais d'habitude,
il s'agit d'objet de type TList, provenant de Borland).

template <typename DataItem> class DsList :
public std::auto_ptr <std::list <DataItem> > {
public:
DsList (void) :
std::auto_ptr <std::list <DataItem> > (new std::list <DataItem>)
{
std::cout << "DsList::DsList" << std::endl;
}
~DsList (void) {
std::list <DataItem>::iterator ItList;
std::cout << "DsList::~DsList" << std::endl;
}
};

int main (int argc, char **argv) {
DsList <DsItem *> pList;
pList->push_back (new DsItem ());
}

Le soucis que j'obtiens lorsque j'essaie de compiler le code,
proviendrait de l'iterator que j'essaie de créer dans le destructeur de
ma classe.

J'espérais pouvoir réaliser cela assez facilement, mais j'ai
l'impression que le type donné au template n'est pas pris en
considération et que cela pose problèmes.

Voici d'ailleurs l'erreur retournée par g++.

bash-2.05b$ g++ dsList.cc -o dsList.x
dsList.cc: In destructor `DsList<DataItem>::~DsList()':
dsList.cc:26: error: expected `;' before "ItList"
dsList.cc: In destructor `DsList<DataItem>::~DsList() [with DataItem =
DsItem*]':
dsList.cc:32: instantiated from here
dsList.cc:26: error: dependent-name `std::list<DataItem,
std::allocator<_CharT> >::iterator' is parsed as a non-type, but
instantiation yields a type
dsList.cc:26: note: say `typename std::list<DataItem,
std::allocator<_CharT> >::iterator' if a type is meant
bash-2.05b$

Version de g++ :
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.4.2 [FreeBSD] 20040728


Auriez-vous une idée ?

Merci d'avance,

PS : Je continue à chercher et à RTFM.

8 réponses

Avatar
Fabien LE LEZ
On Fri, 15 Jul 2005 23:31:05 +0200, Stephane Wirtel
:

public std::auto_ptr <std::list <DataItem> > {


Attention, si je ne m'abuse, auto_ptr, comme les conteneurs de la STL,
dont explicitement prévus pour n'être pas dérivés.

~DsList (void) {


"~DsList()" suffit.

"~DsList (void)", c'est l'écriture utilisée en C.

dsList.cc:26: note: say `typename std::list<DataItem,
std::allocator<_CharT> >::iterator' if a type is meant


Ce message veut dire que le compilateur suppute que tu aurais dû
écrire :

typename std::list<DataItem, std::allocator<_CharT> >::iterator

ou
typename std::list<DataItem >::iterator
le deuxième argument template étant celui par défaut.

Avatar
Fabien LE LEZ
On Sat, 16 Jul 2005 01:35:14 +0200, Fabien LE LEZ
:

dont explicitement prévus


"sont", bien sûr :-(
Toutes mes excuses.

Avatar
Stephane Wirtel
Fabien LE LEZ wrote:
On Sat, 16 Jul 2005 01:35:14 +0200, Fabien LE LEZ
:


dont explicitement prévus



"sont", bien sûr :-(
Toutes mes excuses.

Bonjour Fabien,


Excuse moi, mais même en faisant une recherche sur le texte original du
message du thread, il m'a été impossible de trouver "dont explicitement
prévus".

Ne te serais-tu pas trompé de message ?

Bien à toi,

Stéphane


Avatar
Fabien LE LEZ
On Sat, 16 Jul 2005 07:23:30 +0200, Stephane Wirtel
:

mais même en faisant une recherche sur le texte original du
message du thread, il m'a été impossible de trouver "dont explicitement
prévus".


Comme le champ "References" l'indique, j'ai répondu à
<news:, message que j'avais
moi-même écrit (avec une faute de frappe).

Si tu as du mal à suivre l'enchaînement du thread, c'est normal, il
est tôt. Prends un café et ça devrait aller mieux.

Avatar
Stephane Wirtel
Fabien LE LEZ wrote:
On Sat, 16 Jul 2005 07:23:30 +0200, Stephane Wirtel
:


mais même en faisant une recherche sur le texte original du
message du thread, il m'a été impossible de trouver "dont explicitement
prévus".



Comme le champ "References" l'indique, j'ai répondu à
<news:, message que j'avais
moi-même écrit (avec une faute de frappe).

Si tu as du mal à suivre l'enchaînement du thread, c'est normal, il
est tôt. Prends un café et ça devrait aller mieux.

Fabien,


Inutile que je prenne du café le matin, le problème semble venir du
serveur de news sur lequel je suis abonné (news.brutele.be).

D'après mon thunderbird, il ne me montre qu'un thread avec 4 messages,
par contre, en regardant les news sur google, je peux constater
effectivement que tu m'avais répondu à 01:35 du matin, réponse que je
n'ai pas reçu via le serveur de news de mon provider.

Effectivement, comme tu le dis dans ta toute première réponse, il faut
que j'emplois typename, oubli de ma part je te l'accorde.

template <typename DataItem> class DsList :
public std::auto_ptr <std::list <DataItem> > {
public:
DsList () : std::auto_ptr <std::list <DataItem> > (new std::list
<DataItem>) {
std::cout << "DsList::DsList" << std::endl;
}
virtual ~DsList () {
typename std::list <DataItem>::iterator ItList;
for (ItList = this->get ()->begin (); ItList != this->get
()->end (); ++ItList) {
delete *ItList;
}
std::cout << "DsList::~DsList" << std::endl;
}
};

int main (int argc, char **argv) {
DsList <DsItem *> pList;
pList->push_back (new DsItem ("Texte Libre"));
}

L'idée de cette classe est donc, de libérer automatiquement les items
stockés dans une std::list ou dans mon cas que j'essaie de résoudre, une
TList de Borland, qui ne libère que le tableau de pointeur et non les
données allouées dans la TList.

Mais je constate tout de même que mon destructeur ~DsList n'est pas fort
"beau", car dans le cas ou je ne passe plus des pointeurs comme argument
de mon template, le delete "delete *ItList" du destructeur sera faussé.

Aurais-tu une manière élégante de résoudre ce problème ?

Je m'en excuse encore, mais je n'ai pas reçu ta réponse de cette nuit.

Merci d'avance,

Stéphane


Avatar
Fabien LE LEZ
On Sat, 16 Jul 2005 10:02:57 +0200, Stephane Wirtel
:

L'idée de cette classe est donc, de libérer automatiquement les items
stockés dans une std::list ou dans mon cas que j'essaie de résoudre, une
TList de Borland, qui ne libère que le tableau de pointeur et non les
données allouées dans la TList.


Je vois deux solutions :
- stocker des objets dans ta liste, pas des pointeurs ;
- utiliser autre chose que TList, puisqu'il ne convient pas.
Éventuellement, une dérivée de TList, si cette classe se laisse
dériver, i.e. si elle a un destructeur virtuel.

Pourquoi veux-tu utiliser la classe de chez Borland, au fait ?

Avatar
Stéphane Wirtel
Parce que je développe une APi en C++ Builder, et qu'elle doit
s'interfacer avec une ISAPI écrite via Delphi.

Et comme le code actuel emploit énormément de TList, je me vois mal
tout mettre en std::list en quelques heures, surtout que ce temps là,
je dois l'utiliser pour faire évoluer l'API en fonctionnalités
supplémentaires.

Le refactoring du code se fera d'ici quelques mois, et là, j'aurais
toutes les possibilités de faire un code portable à l'aide de la STL,
mais actuellement, je suis un peu limité à cause de Borland.

Stef
Avatar
Alexandre
bonjour,

L'idée de cette classe est donc, de libérer automatiquement les items
stockés dans une std::list ou dans mon cas que j'essaie de résoudre, une
TList de Borland, qui ne libère que le tableau de pointeur et non les
données allouées dans la TList.


attention, auto_ptr n'est pas vraiment fait pour ça. Outre le fait qu'elle
ne possède pas de destructeur virtuel (donc attention à l'héritage), lors
d'une affectation l'auto_ptr initial "perd" la ressource. Attention si ton
conteneur (TList) utilise des appels par valeur, ou tout autre type...

L'idéal serait d'utiliser un pointeur intelligent, certes, mais pas auto_ptr
(qui ne l'est pas assez ;-))
cherche du coté des "shared ptr" qui possèdent un compteur d'instances et
peuvent donc être utilisés dans des conteneurs, comme ceux de la STL ou ceux
de la VCL, même en cas de passage par valeur ou autre affectation...
La classe n'est pas très compliquée à écrire mais sinon tu as
boost::shared_ptr (ou un nom similaire, je ne l'utilise pas)

Bonne chance