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

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

4 réponses
Avatar
meow
J'aimerai =E9crire une fonction foo(iterateur begin, iterateur end) qui
soit ind=E9pendante du type d'it=E9rateur donn=E9 (list, vector,
autre...) ... De base je pense =E0 un truc du genre :

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

mais =E7a me semble bricolo... Il y a une fa=E7on propre de faire je
suppose.

4 réponses

Avatar
Fabien LE LEZ
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
}
}

Avatar
James Kanze
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

Avatar
meow
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.

Avatar
James Kanze
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