-
Notifications
You must be signed in to change notification settings - Fork 16
/
iterator.txt
497 lines (430 loc) · 28.2 KB
/
iterator.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
ITERATOR
HEADER ==> #<boost/iterator/iterator_concepts.hpp>
DU BON USAGE DES # - utiliser les iterators dès que possible
ITERATORS ==> # - préférer des instantiations temporaires via
# make_* d'iterator_adaptor.
# - utiliser les algorithmes, et éviter les boucles,
# notamment for ( ; ITVR != ITVR2 ; ITVR++ )
# - si un type d'iterator est répété, faire un typedef
BUT ==> #Les concepts itérateurs de la std:: ne séparent pas le
#traversal concept (comment on déplace l'itérateur) de
#l'access concept (lecture/écriture).
#En conséquence, les itérateurs forward et supérieur
#sont requis d'être Writable, il n'est pas possible de
#les définir read-only.
#De plus, puisque Writable, ils ne peuvent pas
#contenir de "vrais" bool d'un bit, parce qu'impossible
#de renvoyer une référence d'un bit => vector<bool>
#read-only agissant comme std::bitset est impossible.
#Boost sépare donc ces deux concepts.
ACCESS ET TRAVERSAL #Leur namespace est boost_concepts::
CONCEPTS ==> #(le reste est boost::)
#Certains en impliquent d'autres :
#
#ReadableIt. WritableIt.
# +------+-----+
# v
# SwappableIt. LvalueIt.
#
# RandomAccessTr. -> BidirectionalTr. -> ForwardTr. ->
# SinglePassIt. -> IncrementableIt.
#
#Ils impliquent tous la présence des 5 typedefs de
#std::iterator_traits<...> (donc pour une classe, on
#peut simplement définir ces typedefs)
ACCESS CONCEPTS ==> #Voici :
ReadableIterator<T1> #Assignable<T1> et CopyConstructible<T1>
#(VALUE_TYPE) *WVAR_VAL
WritableIterator #T2 est par défaut std::iterator_traits<T1>::value_type
[Concept]<T1[,T2]> #CopyConstructible<T1>
# (T2) *WVAR_VAL (non-const et Convertible en T2)
SwappableIterator<T1> #ReadableIterator et WritableIterator (donc
#std::iter_swap(WVAR_VAL, WVAR_VAL2) disponible)
LvalueIterator<T1> # (VALUE_TYPE&) *WVAR_VAL est une référence
TRAVERSAL CONCEPTS ==> #std::iterator_traits<T1>::iterator_category doit
#avoir un tag >= traversal concept.
#Voici :
IncrementableIterator #Assignable<T1> et CopyConstructible<T1>
<T1> #++WVAR_VAL et WVAR_VAL++
SinglePassIterator<T1> #EqualityComparable<T1>
ForwardTraversal<T1> #std::iterator_traits<T1>::difference_type (respecte
#SignedInteger)
#WVAR_VAL() (default constructible)
BidirectionalTraversal #
<T1> #--WVAR_VAL et WVAR_VAL--
RandomAccessTraversal # WVAR_VAL ±= DIFFERENCE_TYPE_VAR
<T1> # WVAR_VAL = WVAR_VAL2 ± DIFFERENCE_TYPE_VAR
# WVAR_VAL = DIFFERENCE_TYPE_VAR + WVAR_VAL2
# DIFFERENCE_TYPE_VAR = WVAR_VAL - WVAR_VAL2
#Requis par RandomAccessIt. en plus (et en théorie,
#selon la doc., mais pas dans les faits, par
#RandomAccessTr.) :
# WVAR_VAL = WVAR_VAL[DIFFERENCE_TYPE_VAR]
# LessComparable, GreaterComparable,
# LessEqualComparable, GreaterEqualComparable
AUTRES CONCEPTS ==> #Voici :
IteroperableIterator #T1 et T2 respectent SinglePassIterator
<T1,T2> #(T2)WVAR1_VAL
#(et non l'inverse (intransitif))
RESUME DES TAGS ET
CONCEPTS ==>
- L'ensemble de ces *tag sont des tags disponibles :
- les tr*_tag décrivent le tranversal concept (iterator_category)
- les it*_tag décrivent l'access + tranversal concept (iterator_category et iterator_transversal<...>::type)
- L'ensemble de ces *Iterator et *Traversal sont des concepts disponibles :
- les anciens concepts décrivent à la fois un access et un tranversal concept.
- attention, les anciens concepts ne demandent pas forcément l'ensemble des 5 typedefs d'iterator_traits
- attention à ne pas confondre par exemple ForwardIt. et ForwardTr.
+-----------------------------+--------------------------+--------------------------+-------------------+
| TAG | ACCESS+TRANVERSAL CONCEPT| ACCESS CONCEPT | TRANVERSAL CONCEPT|
+-----------------------------+--------------------------+--------------------------+-------------------+
| no_tr*_tag | | | Aucun |
| incrementable_tr*_tag | | | IncrementableIt. |
| single_pass_tr*_tag | | | SinglePassIt. |
| forward_tr*_tag | | | ForwardTr. |
| bidirectional_tr*_tag | | | BidirectionalTr. |
| random_access_tr*_tag | | | RandomAccessTr. |
+-----------------------------+--------------------------+--------------------------+-------------------+
| | | WritableIt. | |
| | | ReadableIt. | |
| | | SwappableIt. | |
| | | LvalueIt. | |
+-----------------------------+--------------------------+--------------------------+-------------------+
| std::output_it*_tag | OutputIt. | WritableIt. | IncrementableIt. |
| std::input_it*_tag | InputIt. | ReadableIt. | SinglePassIt. |
| std::forward_it*_tag | Mutable_ForwardIt. | SwappableIt. + LvalueIt. | ForwardTr. |
| | ForwardIt. | ReadableIt. + LvalueIt. | ForwardTr. |
| std::bidirectional_it*_tag | Mutable_BidirectionalIt. | SwappableIt. + LvalueIt. | BidirectionalTr. |
| | BidirectionalIt. | ReadableIt. + LvalueIt. | BidirectionalTr. |
| std::random_access_it*_tag | Mutable_RandomAccessIt. | SwappableIt. + LvalueIt. | RandomAccessTr. |
| | RandomAccessIt. | ReadableIt. + LvalueIt. | RandomAccessTr. |
+-----------------------------+--------------------------+--------------------------+-------------------+
TAGS ==> #Les instantiations d'itérateurs checkent que le tag
#remplisse bien les concepts, donc les algorithmes
#utilisant des itérateurs ont juste à checker leur
#tags et non les concepts.
iterator_traits #
<TYPE>:: #
iterator_category #Renvoie le *tag de TYPE.
iterator_transversal #
<ITERATOR>::type #Renvoie le tr*_tag de TYPE.
HEADER ==> #<boost/iterator_adaptors.hpp>
iterator_facade <WVAR1, #Classe simplifiant la définition de ses propres
WVAR2, WVAR3[, WVAR4 #itérateurs, en garantissant que les concepts voulus
[, WVAR5]]> #soient remplis.
#Il faut le faire hériter (public) par son propre
#itérateur :
# - ce dernier étant de type WVAR1
# - WVAR2 est la value_type
# - WVAR3 l'iterator_category (tr*_tag recommandé)
# - WVAR4 la reference (par défaut WVAR2&). Peut
# être boost::use_default, si l'on veut redéfinir
# WVAR5 mais pas WVAR4.
# - WVAR5 la difference_type (par défaut
# std::ptrdiff_t)
#La classe itérateur enfant WVAR1 doit simplement
#définir les fonctions qui suivent, et non implémenter
#les opérateurs ++, --, ->, etc. elle-même. Les "const"
#sont importants.
#Ainsi :
# - le traversal concept sera == WVAR3
# - l'access concept dépend de WVAR4 (car c'est le
# return type de dereference()) :
# - toujours -> ReadableIt.
# - référence -> LvalueIt.
# - non-const -> WritableIt.
# Il vaut mieux que WVAR2 et WVAR4 aient la même
# constness.
# Les opérateurs sous-jacents -> et [] renvoie une
# WVAR4_VAL (donc une référence seulement si WVAR4
# est une référence)
# Pour permettre instantiation d'iterators
# Writable ou non, mettre un template à l'enfant
# d'iterator_facade pour décrire WVAR4, et mettre
# des typedefs const_iterator et iterator :
# template <class T>
# MonIto : iterator_facade<MonIto<T>, T, ...> {};
# typedef MonIto<TYPE> MonIterateur;
# typedef MonIto<TYPE const> Mon_const_Iterateur;
#Possède des typedefs identiques à ceux
#d'iterator_traits : iterator_facade<...>::value_type,
#etc.
#Penser à cacher de l'interface publique les membres
#dereference(), etc. en les mettant private, et en
#rajoutant :
# friend class boost::iterator_core_access;
#Cela permet d'utiliser les opérateurs sous-jacents
#sans exposer dereference(), etc.
#Cependant, mettre les constructors et destructors en
#public.
#Le RandomAccessTr. implémente aussi les opérations
#requis pour RandomAccessIt. (<, <=, >=, > et [])
#TOUS ==>
WVAR1(const WVAR1&) #Copy constructor
WVAR1(...) #Tout autre constructor que l'on souhaite.
#INTEROPERABLE AVEC WVAR2 ==>
WVAR1(const WVAR2&)
WVAR1 = const WVAR2& #Assignement. Renvoie un const WVAR1&
#READABLEIT. OU WRITABLEIT. ==>
WVAR1.dereference(void) #Comme *WVAR1. Renvoie donc l'élément courant sous forme
const #de WVAR4 (attention return type doit être de la même
#constness que WVAR4. Notamment, si return type vient
#d'une CLASSDT (non déréférencée) de WVAR1, et que WVAR4
#est non-const,#il faut renvoyer const_cast<WVAR4>
#(return type)
#INCREMENTABLEIT. ==>
WVAR1.increment(void) #Comme WVAR1++, mais ne renvoie rien.
#SINGLEPASSIT. ==>
WVAR1.equal #Comme ( WVAR1 == WVAR1 ). Renvoie donc true si WVAR1
(const WVAR1&) const #et WVAR1 ciblent le même container à la même
#position.
#FORWARDTR. ==>
WVAR1() #Constructor par défaut.
#BIDIRECTIONALTR. ==>
WVAR1.decrement() #Comme WVAR1--, mais ne renvoie rien.
#RANDOMACCESSTR. ==>
WVAR1.advance(WVAR5) #Comme WVAR1 += WVAR5 (qui peut être négatif), mais ne
#renvoie rien.
WVAR1.distance_to(const #Comme WVAR1 - WVAR1, renvoie donc le nombre
WVAR1&) const #d'itérations séparant les deux, sous forme de WVAR5.
iterator_adaptor<WVAR1, #Permet de former un nouvel itérateur à partir d'un
WVAR2[, WVAR3[, WVAR4 #autre, mais avec une nouvelle capacité.
[, WVAR5[, WVAR6]]]]]> #Est en fait une spécialisation d'iterator_facade,
#dont il définie automatiquement decrement(...),
#dereference(...), etc., en fonction de l'iterator
#de base :
# - WVAR1 est la classe elle-même
# - WVAR2 est la classe sous-jacente
# - les paramètres suivant sont ceux du template
# de la classe sous-jacente (par défaut ceux
# déjà définis par elle). Peut utiliser
# boost::use_default si l'on veut redéfinir certains
# paramètres mais pas ceux qui précèdent.
# - si l'on ne connait pas le concept maximal de
# l'iterator sous-jacent, plutôt que d'imposer un
# WVAR4, il vaut mieux définir (si possible) toutes
# les fonctions pour le concept maximal, même si
# l'iterator sous-jacent aura peut-être un concept
# inférieur. Penser donc dans ce cas à définir
# toutes ces fonctions.
#On peut modifier le comportement du type sous-jacent
#en redéfinissant decrement(...), dereference(...), etc.
#De même qu'iterator_facade, il faut les mettre private
#et mettre friend class iterator_core_access.
#Ces modifications peuvent ajouter des concepts au type
#sous-jacent.
#Il n'est pas possible de comparer un iterator adaptor
#avec son type sous-jacent. Donc pour comparer par
#exemple avec container.end(), qui renvoie un itérateur
#sous-jacent et non un iterator adaptor, il faut créer
#un deuxième iterator adaptor initialisé avec
#container.end()
#Possède des typedefs identiques à ceux
#d'iterator_traits : iterator_adaptor<...>::value_type,
#etc.
#Plutôt que d'utiliser un iterator_facade dont le type
#sous-jacent est un iterator (par exemple un pointeur),
#utiliser un iterator_adaptor.
#Tous les iterator adaptors ont les membres :
ITERATOR_ADAPTOR() #
ITERATOR_ADAPTOR
(WVAR2_VAL)
: ITERATOR_ADAPTOR<...> #Instantie avec une instance du type sous-jacent.
::iterator_adaptor_ #L'instantiation d'iterator_adaptor_ (typedef depuis
(WVAR2_VAL) #classe parente) semble nécessaire à cause du CRTP.
base_type #Typedef depuis WVAR2
ITERATOR_ADAPTOR.base() #Renvoie l'ITERATOR sous-jacent, sous forme de const&.
ITERATOR_ADAPTOR. #Renvoie l'ITERATOR sous-jacent, sous forme de &, const
base_reference() #si ITERATOR_ADAPTOR est const.
#Ce tableau résume les concepts minimaux requis par
#l'iterator sous-jacent pour un iterator adaptor donné,
#ainsi que les concepts de l'iterator adaptor produit.
#Une case vide désigne :
# - dans la première colonne, que tout iterator
# sous-jacent est possible
# - dans la seconde, que les concepts de l'iterator
# sous-jacent sont conservés.
#--------------------------+-------------+--------------
# ITERATOR ADAPTOR | MINIMUM | RESULTAT
#--------------------------+-------------+--------------
# transform_iterator | readable |
# counting_iterator | | readable
# | | lvalue
# filter_iterator | readable |
# | singlepass |
# function_output_iterator | | writable
# | |incrementable
# indirect_iterator | |
# reverse_iterator |bidirectional|
# permutation_iterator | readable |
# |random access|
# zip_iterator | readable | readable
# shared_container_iterator| |
#--------------------------+-------------+--------------
make_ITERATOR_ADAPTOR #Renvoyant un ITERATOR_ADAPTOR instantié avec ...
(...) #Par exemple make_filter_iterator(...)
HEADER ==> #<boost/iterator/indirect_iterator.hpp>
indirect_iterator<WVAR1 #WVAR1 est le type de l'iterator sous-jacent.
[, WVAR2[, WVAR3 #Fait que *INDIRECT_ITERATOR effectue en fait
[, WVAR4[, WVAR5]]]]> #**INDIRECT_ITERATOR. Un * supplémentaire est aussi
#effectué pour toutes les opérations : ++, etc.
#Utile donc sur un container de pointeurs.
#Les arguments suivants du template sont ceux
#d'iterator_adaptor.
INDIRECT_ITERATOR() #Constructor vide.
INDIRECT_ITERATOR(WVAL1)
HEADER ==> #<boost/iterator/reverse_iterator.hpp>
reverse_iterator<WVAR> #WVAR1 est le type de l'iterator sous-jacent.
#Fait que ++ et --, + et - sont inversés.
#Corrige certaines incompatibilités de std::
#reverse_iterator avec boost.
REVERSE_ITERATOR() #Constructor vide.
REVERSE_ITERATOR(WVAL) #Attention : le constructor est explicit. WVAL est bien
#l'iterator sous-jacent, donc par exemple begin() et
#non rbegin().
HEADER ==> #<boost/iterator/transform_iterator.hpp>
transform_iterator #WVAR1 respecte UnaryFunction
<WVAR1, WVAR2[, WVAR3 #<WVAR1, iterator_traits<WVAR1>::result_type,
[, WVAR4]]> #iterator_traits<WVAR2>::result_type> et possède un
#operator() const.
#WVAR2 est le type de l'iterator sous-jacent. WVAR3
#et WVAR4 modifie la reference et result_type de
#l'iterator sous-jacent (sinon, utilise les valeurs par
#défaut).
#Fait que *TRANSFORM_ITERATOR renvoie
#operator()(*WVAR2), sans pour autant modifier le
#container sous-jacent.
TRANSFORM_ITERATOR() #Constructor vide.
TRANSFORM_ITERATOR
(WVAL2)
HEADER ==> #<boost/iterator/filter_iterator.hpp>
filter_iterator #WVAR1 respecte UnaryPredicate
<WVAR1, WVAR2> #<WVAR1, iterator_traits<WVAR2>::value_type>
#WVAR2 est le type de l'iterator sous-jacent.
#Fait que les itérations ++, --, + et - ne prennent pas
#en compte les itérations (les skippe) renvoyant false
#via WVAR1(*WVAL2).
FILTER_ITERATOR() #Constructor vide.
FILTER_ITERATOR([WVAL1,]#WVAL1 est une instantiation du fonctor WVAR1 (par
WVAL2[, WVAL3]) #défaut un fonctor renvoyant toujours true (utile pour
#un FILTER_ITERATOR instantié sur end() et n'ayant pas
#besoin de WVAL1 donc).
#WVAL2 est l'iterator sous-jacent.
#WVAL3 désigne le moment où le filtre WVAL1 cesse d'être
#appliqué (et où plus aucun élément n'est donc skipped),
#par défaut WVAR2() (c'est-à-dire end()). Il faut pour
#autant toujours mettre WVAL3 sinon ça plante souvent.
#make_filter_iterator() exige que les trois arguments
#soient là.
FILTER_ITERATOR.
predicate() #Renvoie une WVAL1
FILTER_ITERATOR.end() #Renvoie une WVAL3
HEADER ==> #<boost/iterator/counting_iterator.hpp>
counting_iterator #WVAR respecte IncrementableIt.
<WVAR[, WVAR2[, WVAR3]] #Fait que ++ et -- in/décremente *COUNTING_ITERATOR et
#non COUNTING_ITERATOR.
#WVAR2 et WVAR3 sont l'iterator_category et le
#difference_type de WVAR (ceux de WVAR par défaut).
#L'utilité peut être :
# - dans un algorithme, d'avoir des ITVR de début et de
# fin, qui se déréférence à une valeur précise.
# Exemple :
# - std::copy( make_counting_iterator(0),
# make_counting_iterator(7),
# std::back_inserter(VECTOR)), pour remplir VECTOR
# de 8 éléments 0, 1, 2, etc.
# - de remplir un container de pointers :
# - std::copy( make_counting_iterator(ADR),
# make_counting_iterator(ADR + SIZE), ... )
COUNTING_ITERATOR() #Constructor vide.
COUNTING_ITERATOR(WVAL)
HEADER ==> #<boost/function_output_iterator.hpp>
function_output_iterator#WVAR respecte UnaryFunction.
<WVAR> #function_output_iterator est un writable incrementable
#iterator. L'incrémenter n'a aucun effet. Faire :
# - *FUNCTION_OUTPUT_ITERATOR = WVAL2
#invoque WVAL(WVAL2).
#Cela est utile dans un algorithme avec deux ranges, et
#où le deuxième est indiqué par un OUTPUT_ITVR : cela
#permet donc d'appliquer WVAL() à chaque élément du
#premier range.
FUNCTION_OUTPUT_ITERATOR
([WVAL]) #Par défaut WVAR()
HEADER ==> #<boost/iterator/permutation_iterator.hpp>
permutation_iterator #WVAR1 est un type d'iterator pointant sur un container,
<WVAR1, WVAR2> #et respecte RandomAccessTr.
#WVAR2 est un type d'iterator pointant sur un container
#contenant des indexs pour le premier container, et
#respecte ReadableIt.
#iterator_traits<WVAR2>::value_type doit être Convertible
#to iterator_traits<WVAR>::difference_type
#Par exemple, si le deuxième container contient 0, 5 et
#2, les itérations pointeront sur le 1er, puis le 6ème,
#puis le 3ème élément. Peu importe la taille du premier
#container (du moment que le max du premier container
#est <= max du second container, pour que ce soit pas
#out of range).
#S'initialise avec une instance de chaque itérateur.
#Faire ++, --, + ou - itère le second itérateur, qui
#renvoie un index, renvoyant à un élément du premier
#itérateur.
#WVAL1 dans le constructor ne sert donc qu'à indiquer
#quel est l'élément dont l'index est 0 dans le premier
#container, et sa valeur est donc inutile pour
#construire un itérateur de fin.
#De même que ++ et --, les tests != et == comparent le
#deuxième itérateur, qui est donc utilisé uniquement
#pour désigner le début et la fin de l'itération.
PERMUTATION_ITERATOR
(WVAL1, WVAL2)
HEADER ==> #<boost/iterator/zip_iterator.hpp>
zip_iterator <WVAR> #WVAR est un type de tuple<...>.
#ZIP_ITERATOR s'intantie avec un TUPLE d'iterator.
#*ZIP_ITERATOR renvoie un TUPLE de ces iterators
#déréférencés à leur valeur actuelle, et donc
#ZIP_ITERATOR->get<INT_VAL>() renvoie l'iterator numéro
#INT_VAL du tuple, déréférencé.
#Les itérations font bouger chaque iterator du TUPLE.
#ZIP_ITERATOR == ZIP_ITERATOR2, seulement si leur TUPLE
#respectifs sont égaux, donc si tous les éléments des
#deux TUPLE le sont. Ainsi, si ZIP_ITERATOR2 contient
#des end(), il faut que chaque iterator se soit achevé.
ZIP_ITERATOR(WVAL)
HEADER ==> #<boost/iterator/shared_container_iterator.hpp>
shared_container_ #Instantie avec ( T::ITERATOR, SHARED_PTR<T> ),
iterator<T> #où T est un container.
#L'iterator pointe vers T::ITERATOR, mais il partage
#l'ownership du container T_VAR avec le SHARED_PTR.
#But : que l'ITERATOR fasse substituer le range T_VAR
#même si le SHARED_PTR disparaissait.
#En général donc SHARED_CONTAINER_ITERATOR vient d'un
#caller (passé par référence) et SHARED_PTR d'un
#callee.
SHARED_CONTAINER_
ITERATOR( T::ITERATOR,
SHARED_PTR<T> )
make_shared_container_ #Renvoie une std::pair de SHARED_CONTAINER_ITERATOR sur
range( SHARED_PTR<T> ) #le début et fin du container T
HEADER ==> #<boost/pointee.hpp>
pointee<WVAR>::type #Typedef depuis le type WVAR, déréférencé.
#(Marche pour les pointeurs, mais aussi les itérateurs
#et les smart pointers).
#On peut le spécialiser pour le faire marcher avec
#d'autres classes.
HEADER ==> #<boost/indirect_reference.hpp>
indirect_reference #Même chose, mais depuis la référence au type WVAR,
<WVAR>::type #déréférencée.
HEADER ==> #<boost/iterator/iterator_traits.hpp>
iterator_traits #Quasi-identique à std::iterator_traits, mais corrige
#quelques problèmes.
iterator_value<T>::type #Equivaut à boost::iterator_traits<T>::value_type
iterator_reference<T> #
::type #Equivaut à boost::iterator_traits<T>::reference
iterator_pointer<T> #
::type #Equivaut à boost::iterator_traits<T>::pointer
iterator_difference<T> #
::type #Equivaut à boost::iterator_traits<T>::difference_type
iterator_category<T> #
::type #Equivaut à boost::iterator_traits<T>::iterator_category