-
Notifications
You must be signed in to change notification settings - Fork 16
/
variant.txt
98 lines (80 loc) · 7.75 KB
/
variant.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
VARIANT
IDEE ==> #Comme une union, mais plus flexible et puissante.
#On choisit les différents types possibles de la variant compile-time, et on utilise les valeurs
#runtime.
#Est proche des templates, sauf :
# - on connaît les différents types possibles, pouvant paramétrer leur transtypage ou des opérations
# définies (visitors).
#Namespace boost::
#Header :
# - <boost/variant/variant.hpp>
# - <boost/variant/get.hpp>
# - <boost/variant/apply_visitor.hpp>
# - <boost/variant/recursive_wrapper.hpp>
# - <boost/variant/recursive_variant.hpp>
variant<T,U,...> #Classe union-like pouvant être instantiée avec un T ou un U, etc.
#Maximum d'arguments templates : BOOST_VARIANT_LIMIT_TYPES (au moins 10)
#Les types doivent être CopyConstructible, leur destructor nothrow.
#Opérations : assignation, ==, < et << sont possible à condition que les types implémentent ces
#Opérations (et effectue l'opération par rapport à ce type)
#Le "type actuel" est le le type précis utilisé lors de la dernière affectation/initialisation.
VARIANT( [VAL] ) #Instantie VARIANT avec VAL :
# - choisit le type dans le template correspondant exactement à celui de VAL
# - si aucune, choisit un type convertible. Si plusieurs types convertibles : ambiguous compile-time
# error
# - si pas VAL, choisit le default constructor du premier type du template
#Même chose pour affectations.
#Default constructible seulement si le premier type a un default constructor donc.
get<T>( VARIANT ) #Renvoie la valeur de VARIANT, à condition que son "type actuel" soit précisément T.
#Si autre type (même convertible), lance exception bad_get (runtime).
get<T>( VARIANT_ADR ) #Même chose, mais renvoie un pointeur vers cette valeur, et renvoie NULL si problème, là où il aurait
#sinon lancer une exception bad_get.
apply_visitor #FUNCTOR_VAL est une classe :
(FUNCTOR_VAL,VARIANT...)# - dérivant publiquement de static_visitor<U> (<> si U est void)
# - définissant un U operator()( T& ) const, pour chaque T du template de VARIANT.
# operator() peut être une fonction à template, ce qui peut être pratique.
# - si plusieurs VARIANT..., doit avoir défini un U operator()( T&, U&... ) pour toute combinaison
# possible entre les types du template de VARIANT. Nombre maximum de VARIANT : deux.
#Effet : l'operator() pertinent (même sélection que pour instantiation) de FUNCTOR_VAL prend par
#référence la valeur actuelle de VARIANT pour son "type actuel" (et ce pour chaque VARIANT... si
#plusieurs VARIANT...), et renvoie une valeur si operator() non-void.
#L'idée étant que tous les operator() aient le même effet, supprimant l'idée même qu'il existe un
#"type actuel".
#FUNCTOR_VAL peut :
# - effectuer un simple transtypage vers un type donné. Ainsi, une VARIANT avec un tel functor pour
# chacun de ses types peut être toujours transtyper vers n'importe lequel de ses types.
# - effectuer n'importe quelle fonction, getter ou setter. L'intérêt étant juste de définir une telle
# fonction pour VARIANT (i.e. pour l'ensemble de ses types possibles).
apply_visitor #Renvoie un fonctor définissant :
( FUNCTOR_VAR ) # - TYPE operator()( VARIANT&... ) { return apply_visitor( FUNCTOR_VAR, VARIANT... ); }
#TYPE est celui renvoyé (ou non, dans ce cas là, pas de return) par l'apply_visitor sous-jacent.
#Peut donc être utilisé comme predicate sur un algorithme ciblant des containers de VARIANT :
#for_each, find, etc.
FONCTOR::result_type #Le fait de faire dériver de static_visitor<T> fait que ce typedef est défini.
VARIANT.which() #Renvoie l'index du "type actuel" de VARIANT.
VARIANT.type() #Renvoie std::typeid( valeur actuelle de VARIANT )
VARIANT.swap( VARIANT2 )#
swap( VARIANT, VARIANT2)
PRENDRE TOUT VARIANT #Une fonction template prenant "tout" VARIANT doit tout de même choisir le nombre de paramètres du
EN ARGUMENT ==> #template de VARIANT. Pour vraiment prendre tout VARIANT, quel que soit le nombre d'arguments de son
#template (max : BOOST_VARIANT_LIMIT_TYPES) :
# - template <BOOST_VARIANT_ENUM_PARAMS( typename T )>
# TYPE FONC( variant<BOOST_VARIANT_ENUM_PARAMS( T )> ) { ... }
#La macro est expanded par par exemple "<T0, T1, T2>" ou <Arg0, Arg1> si l'on écrit Arg au lieu de T.
INCOMPLETE TYPES ==> #Les types incomplets dans le template de VARIANT ne sont possibles que si l'on écrit :
# - ou variant<recursive_wrapper<T> > au lieu de variant<T>
# - ou make_recursive_variant<T> : préférer celui du dessus
#Utilité possible de types incomplets avec variant : un tree binaire de noeuds T, où T est
#variant<T,U> chaque noeud stocke ou une valeur U ou un nouveau noeud T.
AUTRES ==> #Intéressant, mais pas supporté par Borland :
# - make_[recursive_]variant_over : instantie une VARIANT avec des types boost::MPL
PORTABILITE ==> #variant<T&,...> est pas portable sur IntelC++ 7.0, CodeWarrior 8.3 et MSVC++ 6. Si un compiler
#supporte pas,BOOST_VARIANT_NO_REFERENCE_SUPPORT sera defined (inclure <boost/variant/variant_fwd.hpp>)
/=+===============================+=\
/ : : \
)==: A FAIRE :==(
\ :_______________________________: /
\=+===============================+=/
- VARIANT::types : apprendre MPL