Comment gérer des iterateurs génériques en argument de fonction ?

Le
meow
J'aimerai crire une fonction foo(iterateur begin, iterateur end) qui
soit indpendante du type d'itrateur donn (list, vector,
autre) De base je pense un truc du genre :

template <class iterateur, class type> foo (iterateur<type>
b,iterateur<type> e) {
for (iterateur it=b;it!=e;++it)

}

mais a me semble bricolo Il y a une faon propre de faire je
suppose.
Vos réponses
Trier par : date / pertinence
Fabien LE LEZ
Le #302405
On 12 Feb 2007 06:29:34 -0800, "meow"
J'aimerai écrire une fonction foo(iterateur begin, iterateur end) qui
soit indépendante du type d'itérateur donné (list, vector,
autre...)


template <class Iterateur> void f (Iterateur x, Iterateur fin)
{
for (; x != fin; ++x)
{
// faire quelque chose avec x
}
}

James Kanze
Le #302404
meow wrote:
J'aimerai écrire une fonction foo(iterateur begin, iterateur end) qui
soit indépendante du type d'itérateur donné (list, vector,
autre...) ... De base je pense à un truc du genre :

template <class iterateur, class type> foo (iterateur<type>
b,iterateur<type> e) {
for (iterateur it=b;it!=e;++it)
...
}

mais ça me semble bricolo...


En plus, ça ne marcherait pas, parce que tu as déclaré iterateur
comme un type, mais tu t'en sers comme un template.

Il existe des paramètres template des template, genre :

template< template < typename T > class Iter, type U >
Iter< U >
foo( Iter< U > ...

Mais je ne crois pas que ce soit ce que tu cherches : ça
n'accepterait pas l'itérateur d'un vector, par exemple, qui
n'est pas un template, mais un member d'un autre template, voire
un typedef dans une classe templatée. (Aussi, je ne suis pas
sûr que tous les compilateurs le supportent.)

La solution classique, comme a dit Fabien, c'est simplement :

template< typename Iter >
Iter
foo( Iter begin, Iter end )
{
// ...
}

Habituellement, on se sert du nom du type pour signaler les
contraints : ForwardIterator, RandomAccessIterator, etc.

Ensuite, à l'intérieur de la fonction, on se sert de
iterator_traits pour se renseigner des types apparentés,
genre :

template< typename Iter >
Iter
foo( Iter begin, Iter end )
{
assert( begin != end ) ;
typename std::iterator_traits< Iter >::value_type
first = *begin ++ ;
// ...
}

N'oublie pas le « typename » ; la norme l'exige, même si ce
n'est pas forcement le cas de certains compilateurs.

Il y a une façon propre de faire je suppose.


Propre, je ne sais pas. C'est une question de goût. Mais ce que
je viens de présenter est assez idiomatique, je crois.

--
James Kanze (GABI Software) email:
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

meow
Le #302398
En fait, la solution de Fabien etait la première qui me soit venue à
l'idée, mais j'étais assez dépité du fait qu'on y exprime pas le ty pe
des objets pointés par l'itérateur.
Et si je ne m'abuse la réponse "propre" est là :
typename std::iterator_traits< Iter >::value_type


Implementer le traits qui va bien :)

On va finir par faire quelque chose de bien avec moi ;)
Merci à vous deux.

James Kanze
Le #303158
meow wrote:
En fait, la solution de Fabien etait la première qui me soit venue à
l'idée, mais j'étais assez dépité du fait qu'on y exprime pas le type
des objets pointés par l'itérateur.
Et si je ne m'abuse la réponse "propre" est là :
typename std::iterator_traits< Iter >::value_type


Implementer le traits qui va bien :)


Dans ce cas-là, c'est la bibliothèque standard qui implémente
les traits. Avec une implémentation par défaut qui prend des
valeurs de la classe, et une spécialisation partielle pour les
pointeurs (puisqu'on ne peut pas prendre des valeurs de la
classe sans classe).

--
James Kanze (GABI Software) email:
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


Publicité
Poster une réponse
Anonyme