Bonjour à tous.
J'ai une question assez délicate à gérer.
Pour d'obscures raisons d'architecture tordue, j'ai plusieurs séries de choses ainsi conçues:
Et bien évidemment, la majorité de mon code est de la forme:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 typedef ... Bidule; class Machin { private: list<Bidule> bidules; public: list<Bidule>::const_iterator bidules_begin() const; list<Bidule>::const_iterator bidules_end() const; }; class GrosMachin { private: list<Machin> machins; public: list<Machin>::const_iterator machins_begin() const; list<Machin>::const_iterator machins_end() const; };
Comme il n'y a jamais de code qui n'est pas dans la boucle interne, j'essaie d'écrire une template d'iterateur masquant la double structure.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 GrosMachin g; for (... it_m = g.machins_begin(); it_m != g.machins_end(); ++it_m) { //PAS de code ici for (... it_b = it_m.bidules_begin(); it_b != it_m.end(); ++it_b) { //traiter le Bidule *it_b } //Pas de code ici non plus }
Pour l'essentiel, je l'ai, il "suffit" d'avoir un operateur++ tel que:
Avec la subtilité que le state permet de ne pas stocker le outer.end() dans l'iterateur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 deep_iterator & operator++() { unlazy(); if (++inner_it == inner_end()) { ++outer_it; state = pending_begin; } return *this; }
Logiquement, pour accéder aux bonnes fonctions begin et end, je passe par une classe de trait/police
Comme ca, il suffit de la surcharger pour mon cas particulier, et tout marche tout seul.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 template <typename T> struct IterableTraits { typedef typename T::iterator iterator; typedef typename T::const_iterator const_iterator; static const_iterator begin(T const& t) {return t.begin();} static iterator begin(T & t) {return t.begin();} static const_iterator end(T const& t) {return t.end();} static iterator end(T & t) {return t.end();} };
J'envisage éventuellement d'avoir en template les pointeurs de fonctions vers begin et end, plutot que des statiques. à méditer...
Par contre, j'ai un gros soucis sur un autre point.
J'ai plusieurs cas de map<string, map<string, Truc> >, où l'on veut parcourir l'ensemble des Truc.
Et là, ca devient délicat, car ma template d'itérateur doit subitement devenir capable de discriminer les map (et multimap) des autres types, parce qu'il ne faut pas utiliser [c]*it[c] mais it->second.
La solution qui me semble la moins violente, c'est de passer par une template auxilliaire, qui ferait le bon choix. Et c'est là que je suis perdu.
A priori, la différence entre les deux genres d'accès, c'est qu'il existe un typename It::value_type::second_type.
Je tourne et retourne mon problème, sans parvenir à lui trouver une solution fonctionnelle.
J'ai essayé des choses comme:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 //SFINAE :D template<typename It> typename It::value_type::second_type & iterator_value(It const& it) {return it->second;} template<typename It> typename It::reference iterator_value(It const& it) {return *it;}Mais mon cher compilateur s'entête à considérer les fonctions comme ambigües, ce qui est assez logique.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 //SFINAE deduction template<typename It> typename It::value_type::second_type & iterator_value(It const& it, typename It::value_type::second_type* =0) {return it->second;} template<typename It> typename It::reference iterator_value(It const& it) {return *it;}
Une partie de mon problème étant que je suis coincé avec un compilateur naphtalinien (Visual 2008), qui refuse les valeurs par défaut pour les paramètres template des templates de fonction. (et aussi, refuse le C++11)
Bien évidemment, je n'ai pas non plus le droit d'utiliser boost. (je peux à la rigueur importer un petit fragment, pour peu qu'il n'y ait pas une dizaine d'autres entêtes à importer)
Quelqu'un a-t-il une idée pour écrire cette SFINAE?
Partager