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

implementer un iterateur de X sur un std::vector< std::vector >

31 réponses
Avatar
meow
Tout est dit dans le titre.
Pour faire court j'ai une classe qui contient un vector< vector X >
(o=F9 X est une classe) et j'aimerai it=E9rer sur tous les X contenus
dans ce vecteur de vecteurs. Je m'interroge donc sur la meilleure
fa=E7on de faire. J'imagine que la probl=E9matique est classique mais je
n'ai rien trouv=E9 sur le sujet.

On m'a souffl=E9 une solution facile : ma classe it=E9rateur contiendrait
un vector< X >, mise =E0 plat du vector<vector<X>> ainsi qu'un
it=E9rateur sur ce vecteur (appellons le it).
Je d=E9finirais alors mes op=E9rateurs ++, * et Cie simplement en les
d=E9l=E9guants =E0 it (i.e le ++ de mon it=E9rator fait juste un ++it, et
le * renvoie *it).

Cette solution me parrait lourdingue : si les vector<X> contiennent
beaucoup de X, mon it=E9rateur va bouffer beaucoup de m=E9moire. En
outre, contrairement aux it=E9rateurs de la stl, si ma structure tombe,
mon it=E9rateur continue =E0 etre valide (est-ce important ? Je suppose
que =E7a l'est si je veux faire des delete, replace, remove etc... mais
sinon ?) J'ai donc pens=E9 =E0 une autre solution :

dans mon_iterateur je stockerais un tableaux de paires d'it=E9rateurs
sur X. Chaque paire =E9tant constitu=E9e d'un it=E9rateur sur le d=E9but et
d'un it=E9rateur sur la fin d'un =E9l=E9ment de mon vector<vector<X>>.
J'aurai en outre encore un it=E9rateur sur mon vecteur de paire.
en gros :
class mon_iterateur {
vector<pair<vector<X>::iterator,vector<X>::iterator>> ;
vector<pair<vector<X>::iterator,vector<X>::iterator>> it;
.=2E.
mon_iterateur& operator++ {
if ((*it).first =3D=3D (*it).second) ++it else ++(*it);
return *this;
}
.=2E.
};

=E7a vous semble correct ? y a t'il mieux ?

10 réponses

1 2 3 4
Avatar
meow
J'aurai peut etre du préciser que je m'interresse aux forward
iterators, et que dans le cas d'un iterateur bidirectionnel il faudrait
certainment que je considère un vecteur de triplet d'itérateurs
plutot qu'un vecteur de paires d'itérateurs...
Avatar
Fabien LE LEZ
On 11 Jan 2007 02:04:28 -0800, "meow" :

Pour faire court j'ai une classe qui contient un vector< vector X >
(où X est une classe) et j'aimerai itérer sur tous les X contenus
dans ce vecteur de vecteurs.


Attention, un "vector" n'est absolument pas un vecteur au sens
mathématique du terme. Le vecteur mathématique serait plutôt
valarray<>, tandis que le seul "nom français" auquel je pourrais
penser pour vector<> est "tableau".


Faire un tel const_iterator est simple. Cf code ci-dessous, bricolé en
dix minutes et pas testé.
Pour un iterator, c'est peut-être un peu plus délicat, mais pas très
différent.

On peut remplacer "vector" par "list" ou "deque" dans les deux typedef
(voire un seul des deux).

template <class T> class ConstIterVV
{
public:
typedef std::vector <T> Ligne;
typedef std::vector <Ligne> Table;

ConstIterVV (Table const& t)
{
fin= t.end();
if (t.empty())
{
valide= false;
}
else
{
it1= t.begin();
it2= (*it1).begin();
}
}

ConstIterVV ()
: valide (false) {}

T const operator * () const { assert (valide); return *it2; }

ConstIterVV& operator ++ ()
{
assert (valide);
if (++it2 == (*it1).end())
{
++it1;
if (it1 == fin)
{
valide= false;
}
else
{
it2= (*it1).begin();
}
}
return *this;
}

bool operator == (ConstIterVV const& rhs) const
{
if (!valide && !rhs.valide) return true;
return valide && rhs.valide
&& it1==rhs.it1 && it2==rhs.it2;
}

//Optionnel
operator Ligne::const_iterator() const { return it2; }

private:
Table::const_iterator it1;
Table::const_iterator fin;
Ligne::const_iterator it2;
bool valide;
};

Avatar
meow
le seul "nom français" auquel je pourrais penser pour vector<> est "tab leau".


J'ai toujours des scrupules à employer le terme "tableau" parce que
pour moi ça fait référence à la notation "[ ]" du C qui est
toujours valable en C++... Mais bon, tu as raison, ça peut encore
moins etre traduit par "vecteur", alors faute de mieux je dirai
"vector" ou "tableau"...

Faire un tel const_iterator est simple. Cf code ci-dessous, bricolé en


tiens, oui, y'a un const dont je n'ai pas parlé... Dans le jargon C++
on dit "non mutable", non ?

if (++it2 == (*it1).end())


...Je reste sans voix.

Merci Fabien

Avatar
Fabien LE LEZ
On 11 Jan 2007 04:37:40 -0800, "meow" :

le seul "nom français" auquel je pourrais penser pour vector<> est "tableau".


J'ai toujours des scrupules à employer le terme "tableau" parce que
pour moi ça fait référence à la notation "[ ]" du C qui est
toujours valable en C++...


Mais très peu utilisée tout de même. Et, stricto sensu, pas vraiment
un tableau -- elle représente plutôt un pointeur vers un élément, avec
l'information "il y en a (peut-être) d'autres juste après en RAM."

Faire un tel const_iterator est simple. Cf code ci-dessous, bricolé en


tiens, oui, y'a un const dont je n'ai pas parlé... Dans le jargon C++
on dit "non mutable", non ?


Je ne crois pas.

Le mot-clé "mutable" indique que le membre ainsi déclaré peut être
modifié, même si l'objet auquel il appartient est const.


Avatar
meow
Tiens, j'avais zappé cette ligne :

operator Ligne::const_iterator() const { return it2; }


Qu'est-ce que ça signifie ?

Avatar
meow
T const operator * () const { assert (valide); return *it2; }


On peut aussi faire comme suit (En supposant que T peut etre gros et
qu'on veut pas payer le cout éventuel de la copie...) ?

T const &operator * () const { assert (valide); return *it2; }

Avatar
Fabien LE LEZ

T const operator * () const { assert (valide); return *it2; }


Je confirme que c'est une faute de frappe.
Il fallait lire "T const& operator...".

Avatar
Fabien LE LEZ
On 11 Jan 2007 05:38:56 -0800, "meow" :

operator Ligne::const_iterator() const { return it2; }


Qu'est-ce que ça signifie ?


C'est l'opérateur de conversion en vector<T>::const_iterator.

ConstIterVV it= ...
vector<T>::const_iterator i= it;


Avatar
meow
C'est l'opérateur de conversion en vector<T>::const_iterator.

ConstIterVV it= ...
vector<T>::const_iterator i= it;


OK, merci encore :)

Avatar
meow
Il y a toujours un truc qui me chagrine dans cette histoire. Comment je
teste ma condition d'arret ? Je veux dire, d'habitude on a quelque
chose du genre :

for ( iterateur i=conteneur.begin() ; i!=conteneur.end() ; ++i)

conteneur.begin() et conteneur.end() devant renvoyer des itérateurs.
Dans notre cas, je suppose qu'en lieu et place de conteneur.begin() on
écrit ConstIterVV(L) (avec L le conteneur) mais pour conteneur.end()
comment s'en sort-on ?
1 2 3 4