-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathgeneric_programming.txt
71 lines (62 loc) · 5.55 KB
/
generic_programming.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
┏━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ GENERIC_PROGRAMMING ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━┛
GENERIC PROGRAMMING ==> #Ecrire un programme où l'on ne précise pas les types des arguments et valeurs utilisées/retournées par
#les fonctions, tout type étant possible.
#But : extensibilité maximum.
#En C++, utilise les templates pour cela, ou le type erasure.
#Proche des templates aussi, mais pour un nombre de types limités mais mieux pris en charge :
#boost::variant.
CONCEPTS ==> #Dans une classe ou une fonction à template <T>, tout type T est possible. Cependant, pour que la
#classe ou la fonction soit correcte, certains pré-requis sont nécessaires. Si la classe ou fonction
#effectue un :
# - *T = VAL
#T doit être par exemple être déréférencable et la valeur déréférencée doit pouvoir être modifiable.
#Ce sont des "minimal requirements". Les "concepts" sont des classes instantiant ces "minimal
#requirements".
#Les concept checks consistent à s'assurer que le type du template remplit les concepts sont respectés
#par T, compile-time.
#Un concept peut en fait désigner tout ce qui est checké par un "design by contract", mais les concepts
#checks se limitent en général aux préconditions.
#Refining un concept est créer un concept ajoutant de nouveaux requirements à un ancien concept.
ASSOCIATED TYPE ET #Une précondition peut être :
VALID EXPRESSION ==> # - une "valid expression" : expression devant être possible et valide (par exemple VAR == VAR)
# - un "associated type" / trait : un type devant être disponible
# - les exceptions pouvant être lancées par le type.
CLASSE DE TRAITS ==> #Template class définissant un ensemble de traits. Utilité :
# - non-intrusif. Possibilité de définir des traits pour des classes non modifiables (Open/close
# principle) ou builtin.
# - regrouper l'ensemble de traits dans une seule classe, plutôt que de définir l'ensemble des traits
# dans chaque type possible devant définir ces traits.
# - pas de perte en flexbilité pour autant : les types devant définir différemment ces traits peuvent
# spécialiser la classe de traits.
# - possibilité de mettre la classe de traits en argument de template d'une fonction générique, et de
# définir plusieurs classes de traits concurrentes, une pour chaque usage. On choisit ensuite la
# famille de traits que l'on veut choisir pour telle instantiation.
#Exemple : iterator_traits, char_traits
POLICY CLASS ==> #Comme classe de traits, mais pour les "valid expressions". Mêmes avantages, avec un accent sur la
#possibilité de choisir la classe de police désiré, pour un "behavior" donné (par exemple, une policy
#class pour la rapidité, une pour la sécurité, etc.)
#Possibilité de regrouper policy class et traits class : char_traits, std::allocator
TAGS ==> #Une fonction générique set d'interface à une série d'overloads, en fonction des concepts remplis par
#les types génériques.
#La sélection de l'overload se fait via une classe vide, "tag", en argument ou en template.
#Exemple :
# template <class T> FONC( CLASS ) { ... }
# template <> FONC<RandomAccessTag>( CLASS ) { ... }
# template <class T> FONC_WRAPPER( ARGS )
# { FONC<typename traits<T>::tag_category>( ARGS ); }
OBJECT GENERATOR ==> #Template fonction prenant un rôle de constructor,en retournant une instantiation d'une template classe
#En effet, la fonction peut se passer de <...>, mais pas une classe et son constructor.
#Ex :
# - make_pair(ARG1, ARG2) au lieu de pair<TYPE1, TYPE2>(ARG1, ARG2)
# - bind2nd(FONCTOR, ARG) au lieu de binder2nd<FONCTOR_TYPE>(FONCTOR, ARG)
#Aussi parfois appelé "helper".
TYPE ERASURE ==> #Sorte de "templates run-time". Permet de passer n'importe quel type, même inconnu compile-time.
#Cela exige un cast vers l'underlying type, runtime.
#Ex : void*, boost::any, boost::function
#Exemple où c'est pertinent : un template <T> doit utiliser, pour une instantiation donnée, le même
#type pour T. Par exemple un std::vector ne peut avoir qu'un type d'élement à la fois, mais pas un
#vector<boost::any>
PIMPL IDIOM ==> #Il s'agit de cacher l'underlying interface (i.e. type erasure) en utilisant un void*, ou plus safe,
#un smart pointer.