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

L'enfer de la STL

27 réponses
Avatar
Alain Ketterlin
Salut,

J'utilise pas mal la STL, avec des combinaisons du genre :

map < pair<Truc*,Truc*> , set<Truc*> > m;

(pour la plus simple). Pour diverses raisons, j'essaie d'éviter les
typedef. Donc je me retrouve avec des boucles comme :

for ( map < pair<Truc*,Truc*> , set<Truc*> >::iterator it=m.begin() ;
it!=m.end() ; it++ )
{ ... }

D'où mes deux questions :

1) y a-t-il plus court ? (Hors for_each, qui ne m'intéresse pas parce
que mes corps de boucle sont éventuellement longs, et je n'ai pas
envie de les rejeter chacun dans une classe.)

2) Quelqu'un a-t-il des informations sur la standardisation
(éventuelle) et l'implémentation de "auto" dans g++ ? Je n'ai rien
trouvé de précis. Quand pourrais-je écrire
for ( auto it=m.begin() ; it!=m.end() ; it++ ) ...


Question subsidiaire : en essayant d'écrire une macro pour remplacer
la tête de boucle ci-dessus, j'ai remarqué que le préprocesseur ne
connait rien aux templates. Si j'écris

#define FOREACH(T,c,v) for ( T :: iterator v=c.begin() ... )

alors il couine sur

FOREACH(pair<Truc1,Truc2>,m,it)

parce qu'il ne comprend pas que la première virgule est entre < et >.
Savez-vous si il est prévu que ça change ?

Merci d'avance. J'espère avoir raté quelque chose d'évident.

-- Alain.

10 réponses

1 2 3
Avatar
Jean-Marc Bourguet
Alain Ketterlin writes:

J'utilise pas mal la STL, avec des combinaisons du genre :

map < pair<Truc*,Truc*> , set<Truc*> > m;

(pour la plus simple). Pour diverses raisons, j'essaie d'éviter les
typedef. Donc je me retrouve avec des boucles comme :

for ( map < pair<Truc*,Truc*> , set<Truc*> >::iterator it=m.begin() ;
it!=m.end() ; it++ )
{ ... }

D'où mes deux questions :

1) y a-t-il plus court ? (Hors for_each, qui ne m'intéresse pas parce
que mes corps de boucle sont éventuellement longs, et je n'ai pas
envie de les rejeter chacun dans une classe.)



Pas que je sache.

Question subsidiaire : en essayant d'écrire une macro pour remplacer
la tête de boucle ci-dessus, j'ai remarqué que le préprocesseur ne
connait rien aux templates. Si j'écris

#define FOREACH(T,c,v) for ( T :: iterator v=c.begin() ... )

alors il couine sur

FOREACH(pair<Truc1,Truc2>,m,it)

parce qu'il ne comprend pas que la première virgule est entre < et >.
Savez-vous si il est prévu que ça change ?



Il n'est pas prevu que ca change (conceptuellement le preprocesseur
fonctionne a un moment ou il est impossible de savoir si pair est un
template ou pas.

Sauf erreur de ma part,

FOREACH((pair<Truc1,Truc2>), m, it)

devrait fonctionner.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Alain Ketterlin
Jean-Marc Bourguet writes:

Alain Ketterlin writes:
#define FOREACH(T,c,v) for ( T :: iterator v=c.begin() ... )

alors il couine sur

FOREACH(pair<Truc1,Truc2>,m,it)

parce qu'il ne comprend pas que la première virgule est entre < et >.
Savez-vous si il est prévu que ça change ?



Il n'est pas prevu que ca change (conceptuellement le preprocesseur
fonctionne a un moment ou il est impossible de savoir si pair est un
template ou pas.



Oh j'espérais plus simple, du genre considérer comme atomique ce qui
se trouve entre < et >, comme il le fait avec ( et ). Ca pourrait être
une option, puique GNU cpp a déjà -x et -std.

Sauf erreur de ma part,

FOREACH((pair<Truc1,Truc2>), m, it)

devrait fonctionner.



Malheureusement non, impossible de caser un type entre parenthèse.

Merci pour ton aide.

-- Alain.
Avatar
Jean-Marc Bourguet
Alain Ketterlin writes:

Jean-Marc Bourguet writes:

> Alain Ketterlin writes:
>> #define FOREACH(T,c,v) for ( T :: iterator v=c.begin() ... )
>>
>> alors il couine sur
>>
>> FOREACH(pair<Truc1,Truc2>,m,it)
>>
>> parce qu'il ne comprend pas que la première virgule est entre < et >.
>> Savez-vous si il est prévu que ça change ?
>
> Il n'est pas prevu que ca change (conceptuellement le preprocesseur
> fonctionne a un moment ou il est impossible de savoir si pair est un
> template ou pas.

Oh j'espérais plus simple, du genre considérer comme atomique ce qui
se trouve entre < et >, comme il le fait avec ( et ). Ca pourrait être
une option, puique GNU cpp a déjà -x et -std.

> Sauf erreur de ma part,
>
> FOREACH((pair<Truc1,Truc2>), m, it)
>
> devrait fonctionner.

Malheureusement non, impossible de caser un type entre parenthèse.



Il y a des endroits dans les types ou on peut mettre des parentheses,
mais pas dans ce qui qualifie les noms.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Fabien LE LEZ
On Thu, 06 Nov 2008 17:29:52 +0100, Alain Ketterlin
:

map < pair<Truc*,Truc*> , set<Truc*> > m;



typedef est ton ami.
Avatar
Mickaël Wolff
Alain Ketterlin a écrit :
(pour la plus simple). Pour diverses raisons, j'essaie d'éviter les
typedef. Donc je me retrouve avec des boucles comme :



Quels peuvent être les raisons qui peuvent pousser à ne pas employer
une technique propre ?

2) Quelqu'un a-t-il des informations sur la standardisation
(éventuelle) et l'implémentation de "auto" dans g++ ? Je n'ai rien
trouvé de précis. Quand pourrais-je écrire
for ( auto it=m.begin() ; it!=m.end() ; it++ ) ...



Ce n'est visiblement pas encore implémenté
<http://gcc.gnu.org/projects/cxx0x.html>


--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Alp Mestan
Il ne faut pas oublier Boost, qui propose un FOREACH assez
intelligent, et qui permet de créer des lambdas expressions.
Ca donne quelque chose comme, avec le for_each de la STL :
for_each(m.begin(), m.end(), cout << _1 << endl);
Cela affichera tous les éléments de m, ou m est un peu ce que tu veux,
pour peu que ses éléments soient affichables.
Avatar
Alain Ketterlin
Mickaël Wolff writes:

Alain Ketterlin a écrit :
(pour la plus simple). Pour diverses raisons, j'essaie d'éviter les
typedef. Donc je me retrouve avec des boucles comme :



Quels peuvent être les raisons qui peuvent pousser à ne pas employer
une technique propre ?



Mon grand age. Quand j'ai une boucle comme :

for ( map < pair<Truc*,Truc*> , set<Truc*> >::iterator it=m.begin() ;
it!=m.end() ; it++ )
{ ... }

le corps de la boucle contient des choses du genre :

... it->first.second ...

Je préfère avoir le type détaillé sous les yeux, plutôt que d'aller
chercher le typedef correspondant. Je n'ai jamais trouvé typedef très
utile (sauf en C), et j'ai tendance à penser que ce n'est guère plus
qu'un prépro. Quitte à être propre, quand c'est nécessaire je définis
une classe, mais alors je suis parti pour le rodéo copy-ctor/op= etc.
Bien sûr tout cela est très subjectif.

Cela dit, au risque d'être sacrilège, pour une boucle comme celle
ci-dessus, le panard ça serait :

for ( entry < pair<Truc*,Truc*> , set<Truc*> > e : m )
{ ... }

ou quelque chose comme cela, mais ça demande une nouvelle syntaxe.

2) Quelqu'un a-t-il des informations sur la standardisation
(éventuelle) et l'implémentation de "auto" dans g++ ? Je n'ai rien
trouvé de précis. Quand pourrais-je écrire
for ( auto it=m.begin() ; it!=m.end() ; it++ ) ...



Ce n'est visiblement pas encore implémenté
<http://gcc.gnu.org/projects/cxx0x.html>



Cool. Dans gcc-4.4 ils auront déjà supprimé l'ancien auto, mais sans
ajouter le nouveau. Un premier pas :-)

-- Alain.
Avatar
Fabien LE LEZ
On Fri, 07 Nov 2008 11:41:08 +0100, Alain Ketterlin
:

Je préfère avoir le type détaillé sous les yeux,



Faudrait savoir.

Avec
for ( auto it=m.begin() ; it!=m.end() ; it++ ) ...
tu ne l'as pas plus sous les yeux !


Quitte à être propre, quand c'est nécessaire je définis
une classe,



Effectivement, les types à rallonge du style map<set<... sont
généralement "locaux", utilisés dans une seule fonction ou dans un
petit groupe de fonctions. Du coup, le typedef est très proche du
code, pas besoin d'aller très loin pour le trouver.

Si j'ai besoin d'un tel type dans un contexte plus global (= défini
dans un .h), je l'encapsule dès le départ dans une classe -- parce que
j'en aurai besoin tôt ou tard.

mais alors je suis parti pour le rodéo copy-ctor/op= etc.



Je ne vois pas pourquoi.

Si les constructeur et opérateur de copie du type

map < pair<Truc*,Truc*> , set<Truc*> >

te conviennent, alors ceux de

class C
{
...
private:
map < pair<Truc*,Truc*> , set<Truc*> > data;
};

devraient te convenir aussi.
Avatar
pjb
Alain Ketterlin writes:

Cela dit, au risque d'être sacrilège, pour une boucle comme celle
ci-dessus, le panard ça serait :

for ( entry < pair<Truc*,Truc*> , set<Truc*> > e : m )
{ ... }

ou quelque chose comme cela, mais ça demande une nouvelle syntaxe.



D'où l'intérêt d'un langage comme Common Lisp qui permet de définir
facilement des nouvelles syntaxes.




Sinon il faut utiliser boost:

// Boost 1.33.3 ; dans boost 1.34, foreach n'est plus "test".
#include <boost/test/utils/foreach.hpp>
#define foreach BOOST_TEST_FOREACH

Ainsi, si on a un conteneur contenant des élément de type Type, on peut écrire:

foreach(Type,element,conteneur){
process(element);
}


--
__Pascal Bourguignon__
Avatar
Fabien LE LEZ
On Fri, 07 Nov 2008 12:18:11 +0100, (Pascal J.
Bourguignon):

D'où l'intérêt d'un langage comme Common Lisp



Tiens, ça faisait longtemps...
1 2 3