This is an old revision of the document!
Partie II – Création d’itérateurs
TD4
Nous considérons un ensemble de nombres entiers correspondant à un interval fermé entre [minValue
, maxValue
] défini par la classe suivante :
class interval
{
private:
int minValue;
int maxValue;
public:
typedef int value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
interval(int theMinValue, int theMaxValue) :
minValue(theMinValue), maxValue(theMaxValue)
{}
interval(const interval& anotherInterval):
minValue(anotherInterval.minValue),
maxValue(anotherInterval.maxValue)
{}
interval& operator = (const interval& anotherInterval)
{
minValue = anotherInterval.minValue;
maxValue = anotherInterval.maxValue;
return *this;
}
size_type size() const
{
return (size_type)(maxValue - minValue);
}
int operator[](size_type anIndex) const
{
if (anIndex > size())
throw std::out_of_range("Index out of range");
return minValue + (int)anIndex;
}
bool operator == (const interval& anotherInterval) const
{
return anotherInterval.maxValue == maxValue &&
anotherInterval.minValue == minValue;
}
bool operator != (const interval& anotherInterval) const
{
return anotherInterval.maxValue != maxValue ||
anotherInterval.minValue != minValue;
}
};
Nous souhaitons pouvoir définir des itérateurs pour pouvoir itérer sur cet interval. Pour ce faire, nous devons ajouter au moins les méthodes suivantes et champs suivants :
friend class interval_iterator;
typedef interval_iterator const_iterator;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
En supposant que la classe itérateur s’appelle interval_iterator.
Il ne reste plus qu’à créer une classe interval_iterator
dont le squelette serait le suivant :
class interval_iterator
: public std::iterator <std::forward_iterator_tag, int>
{
private:
friend class interval;
const interval* mInterval; // Référence à l'interval.
int mCurrent; // la valeur courante dont on fait référence.
interval_iterator(const interval& anInterval, int aCurrentValue) :
mInterval(&anInterval), mCurrent(aCurrentValue) {}
public:
interval_iterator(const interval_iterator& anotherIterator):
mInterval(anotherIterator.mInterval),
mCurrent(anotherIterator.mCurrent) {}
interval_iterator& operator = (interval_iterator& anotherIterator)
{
mInterval = anotherIterator.mInterval;
mCurrent = anotherIterator.mCurrent;
return *this;
}
const reference operator*() const;
const pointer operator->() const;
interval_iterator& operator++();
interval_iterator& operator++(int);
bool operator ==(const interval_iterator&) const;
bool operator !=(const interval_iterator&) const;
};
Question 1.0
Complétez les classes interval
et interval_iterator
afin de pouvoir supporter les itérateurs.
Nous débutons par compléter la classe interval
. La classe 'interval doit exposer au moins deux méthodes que sont les méthodes :
<code cpp>
iterator begin(); Itérateur faisant référence au premier élément
contenu dans le containeur
iterator end(); Itérateur indiquant que l'on a dépassé le dernier
élément de la séquence d'éléments contenus
dans le containeur.
</code>
De plus nous devons définir aussi les types suivants:
<code cpp>
value_type le type des valeurs contenues dans le containeur.
habituellement T
reference un type faisant référence aux valeurs contenues dans
habituellement T&
const_reference un type faisant référence aux valeurs contenues dans
mais empêchant la modification de ces valeurs,
habituellement
T&
iterator iterateur faisant référence aux valeurs contenues dans le containeur
permettant un accès en lecture et écriture de ces valeurs si l'accès
en écriture est supportée par le containeur.
const_iterator itérateur faisant référence aux valeurs contenues dans le containeur
ne permettant qu'un accès en lecture.
difference_type un type d'entier signé qui correspond à la distance entre deux itérateurs,
size_type Un type d'entier non-signé qui correspond au type taille du containeur.
</code>
Dans le cas de notre classe interval
, le type des valeurs est int
, les valeurs ne peuvant pas être modifiées, ce qui induit les définitions suivantes :
<code cpp>
class interval
{
public:
…
typedef const int value_type;
typedef reference const int&;
typedef const_reference const int&;
…
};
</code>
Pour la classe iterator
, nous ne pouvons définir que des itérateurs ne pouvant pas modifier les valeurs contenues dans l'interval. Donc nous définissons les champs comme suit :
<code cpp>
class interval
{
public:
…
typedef interval_iterator iterator;
typedef interval_iterator const_iterator;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
…
};
</code>
Il reste dés lors à définir les fonctions begin
et end
. Pour ce faire, nous définissons les fonctions comme suit :
<code cpp>
class interval
{
public:
…
inline iterator begin() const;
inline iterator end() const;
…
};
class interval_iterator
{
};
inline interval::iterator interval::begin() const
{
return iterator(*this, minValue);
}
inline interval::iterator interval::end() const
{
return iterator(*this, maxValue + 1);
}
</code>
La fonction begin
retourne un objet de type interval_iterator
qui fait référence à l'interval courant et qui fait référence à minValue
qui correspond à la première valeur de l'interval d'entier.
La fonction end
retourne un objet de type interval_iterator
qui fait référence à l'interval courant et qui fait référence à maxValue
qui correspond à la valeur situé après la dernière valeur valide de l'interval, donc fait bien référence à la première valeur située en dehors de la séquence de valeur.
Les fonctions begin
et end
font appel à un constructeur de la classe interval_iterator
. En C++, avant de pouvoir appeller un constructeur, il faut que la classe soit définie. Comme la classe interval_iterator
est définie après la classe interval
, il est nécessaire que le code des fonctions begin
et end
soit située après la classe interval_iterator
. Il n'est pas possible de les définir dans le corps de la classe interval
.
</hidden>
===== Question 2.0 =====
Tester le bon fonctionnement de classe avec le code suivant :
in204/tds/sujets/td4/part2.1571133780.txt.gz · Last modified: 2019/10/15 10:03 by bmonsuez