Hello � tous !!
Est-ce quelqu'un pourrait m'expliquer la notion des traits ? Je trouve �a tr�s abstraits et j'aimerais savoir dans quel situation on s'en sert.
Mercii !!
Hello � tous !!
Est-ce quelqu'un pourrait m'expliquer la notion des traits ? Je trouve �a tr�s abstraits et j'aimerais savoir dans quel situation on s'en sert.
Mercii !!
Je d�veloppe beaucoup en C++ et je ne vois absolument pas de quoi tu veux parler... Mais regarde le tuto "Pr�sentation des classes de Traits et de Politiques en C++".
Cela n'a pas l'air d'�tre un concept tr�s utilis� en C++, si tu es d�butant ne te focalise pas dessus.
Ca marche, en fait c'est un concept que j'avais vu en cours c'est pour �a et je n'avais pas tr�s bien compris la notion.
En industrie, il faudrait se focaliser plus sur l'approche Orient� Objet ?
Je dirais que �a d�pend de ton probl�me. Si les classes de traits te permettent de simplifier ton code, utilise-les. Je n'ai presque jamais utilis� les classes traits (peut-�tre que j'aurais pu/du le faire), mais beaucoup plus souvent les classes de politiques qui me sont extr�mement utiles pour apporter du code depuis l'ext�rieur d'une fonction.
Edit: Je ne sais pas si c'est � proprement parler une classe de traits, mais je place presque toujours des alias de type dans mes classes, certains en public. Ca m'est �galement extr�mement utile pour r�cup�rer de l'information de type depuis l'ext�rieur. La classe fait pleins d'autres choses qu'�tablir des correspondances de types, donc je ne sais pas comment qualifier cet usage.
Quoiqu'il en soit mon -�norme- erreur de d�butant avait �t� de conna�tre et d'utiliser uniquement la programmation orient� objet pour mettre de la flexibilit� dans le code. Ca c'est retourn� contre moi en tr�s peu de temps, car si on ne connait que la POO on finit par �crire du code tr�s compliqu�, avec des hi�rarchies de classes �normes et bien rigides, o� rien ne veut plus rien dire. L'h�ritage est une relation de d�pendance tr�s forte donc prudence, que tu sois en industrie ou pas
Ce forum m'a appris � plut�t aller voir du c�t� des templates, et �a m'a bien simplifi� la vie !
Bon courage,
C'est un concept abstrait puisque �a touche � la m�ta-programmation.
Un trait/tag/politic sera un type que tu passes en template pour param�trer un objet.
Par exemple le 3� param�tre de std::map qui d�finit l'op�rateur de comparaison, en le modifiant tu changes l'ordre d'insertion/de stockage des �l�ments de ta map.
Autre exemple simplet, changer le type de logging selon un trait
Au lieu d'une sp�cialisation via NoLog, on pourrait sp�cialiser le Logger pour void
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class LogToFile { public: LogToFile() { mFile.open("log.txt"); void log(const char* str) { mFile<<str; } private: std::ofstream mFile; }; class LogToCout { public: void log(const char* str) { std::cout << str; } }; class NoLog { public: void log(const char*) {} }; template<class Log> class Logger { public: void log(const char* str) { mLog.log(str); } private: Log mLog; };
Et tu as tout plein de sp�cialisation pour avoir des infos sur les types via type_traits.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6 template<> class Logger<void> { public: void log(const char*) {} };
Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
Un peu de programmation r�seau ?
Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.
Ce que l'on appelle trait/tag/politic c'est juste l'utilisation d'un template ?
Bizarre, il me semble l'avoir expliqu� il y a pas longtemps.
Dans tous les cas, cela sert � l��criture de code g�n�rique (template).
.
.
.
Message retrouv� dans un forum concurrent::
tag et politiques sous-entendent des choses diff�rentes, en plus de traits.
Un trait va renvoyer une info sur un type (cf l'it�rator trait) -- le type peut �tre un tag. Un tag est une structure vide qui va servir � dispatcher via sp�cialisation template & cie. Une politique ressemble au trait sauf qu'il y a un comportement en plus attach� -- cf le vieux /C++ Modern Design/ d'Andrei Alexandrescu.
Ca sert tous les jours quand on utilise des vecteurs, mais ce n'est pas visible de l'utilisateur final. De temps en temps je m'en sers industriellement, mais une fois de plus, c'est pour �crire du code g�n�rique de type boute � outils. Tout le monde n'a pas mettre les mains dedans.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne r�ponds � aucune question technique par le biais de ce m�dia. Et de toutes fa�ons, ma BAL sur dvpz est pleine...
Salut,
De mani�re g�n�rale, un trait est une sorte "d'adaptateur" qui permet de d�terminer quel sera le type r�el d'un terme clairement d�fini.
Par exemple, si je cr�es un trait proche deet que je l'utilise sous la forme deusing IntTrait = MyTrait<int>;, les types repr�sent�s par IntTrait::value_type et celui de IntTrait::return_type seront tous les deux �quivalents de int.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5 template <typename V, R = V> struct MyTrait{ using value_type = V; using return_type = R };
Par contre, si je l'utilise sous la forme de using IntDoubleTrait = MyTrait<int, double>; le type repr�sent� par IntDoubleTrait::value_type correspondra � int et celui repr�sent� par IntDoubleTrait::return_type sera �quivalent � double.
Et je pourrais tr�s bien en fournir une sp�cialisation proche deA partir de l�, vient la notion de politic permet de d�finir l'interface et -- le cas �ch�ant -- des comportements adapt�s � certaines situations et / ou � certains types de donn�es. En cas de besoin, elles peuvent sans aucun probl�me faire appel � des traits afin de d�terminer le type de certains �l�ments.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5 template <> struct MyTrait<std::map<int, std::string>, std::map<int, std::string>>{ using value_type = int; using return_type = typename std::map<int, std::string>::const_iterator; };
Par exemple, je pourrais cr�er une politique proche dequi exposera une fonction foo prenant deux param�tres de type V sous la forme de r�f�rence constante et qui renverra un �l�ment de type R.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5 template <typename V, typename R = V> Policy{ static R foo(V const & a, V const & b); };
Mais si je veux l'utiliser avec une std::map<int, std::string>, je vais avoir quelque probl�mes, parce que R et V ne correspondent finalement � rien dans une std::map.
Je vais donc passer par l'adaptateur (mon trait MyTrait) que j'ai "justement" sp�cialis� pour le traitement de cette drole de b�te;
Et devines quoi? la magie op�re :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7 template <typename V, typename R = V> Policy{ usign value_type = typename MyTrait<V, R>::value_type; using return_type = typename MyTrait<V, R>::return_type; static R foo(V const & a, V const & b); };
- si j'utilise Policy avec un (ou deux) int comme param�tre template, Policy::value_type et Policy::return_type seront tous les deux �quivalent au type int
- si j'utilise Policy avec un int et un double, Policy::value_type sera �quivalent � int et Policy::return_type sera �quivalent � double
- si j'utilise Policy avec un (ou deux) std::map<int, std::string>, Policy::value_type sera �quivalent �... int et Policy::return_type sera �quivalent � ... std::map<int, std::string>::const_iterator
Il n'y a plus que la notion de tag � voir.
Tu le sais sans doute, chaque param�tre template de ton expression (template) intervient dans l'�valuation finale. Par exemple,
te d�finira des types diff�rents si T et/ou U sont de types diff�rents:
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5 template <typename T, typename U> struct MyStruct{ T x; U y; };
- MaStruct<int, double> S1 et MaStruct<int, double> S2 d�finis des donn�es de m�me type parce que les param�tres template sont identique deux � deux, mais
- MaStruct<int, int> S3 et MaStruct<int, double> S4 d�finis des donn�es de type diff�rent, parce qu'il y a (au moins) un param�tre template qui diff�re.
Cela nous conviendra tr�s souvent parfaitement. Mais, il y a quelques circonstances dans lesquelles on pourrait souhaiter que S1 et S2 correspondent � des donn�es... de type diff�rents. Ne serait-ce que parce que ma structure MyStruct peut servir � repr�senter une quantit� invraissemblable de donn�es qui n'ont rien � voir les unes avec les autres, m�me lorsque x est un int et que y est un double.
Il me faut donc disposer d'un moyen de faire la diff�rence entre une MyStruct<int, double> qui repr�sente respectivement le maximum de vie et le niveau "courant" de vie et une MyStrut<int, double> qui repr�sente respectivement le niveau maximum de mana et ... le niveau courant de mana.
C'est tr�s simple � faire : il me suffit de rajouter un param�tre template (un "tag") � MyStruct. C'est un �l�ment qui ne sert � rien d'autre qu'�... permettre de faire la distinction entre une MyStruct<int, double> et une autre MyStruct<int, double> qui sera utilis�e dans un contexte diff�rent:
Si nous avons deux donn�es pour lequel ce dernier param�tre template est identique, nous aurons affaire � deux don�es de type identique, que nous pourrons utiliser "conjointement". Si ce dernier param�tre template est diff�rent, nous devrons utiliser nos donn�es dans des contextes diff�rnts.
Ce que l'on appelle trait et politic sera souvent un �l�ment template, avec ou sans sp�cialisation partielle ou totale.
Pour ce qui est des tags, qui n'ont -- comme je viens de l'expliquer -- pour seul objectif que de permettre de faire la distinction entre deux sp�cialisation d'une classe ou d'une structure en cas de besoin, le seul imp�ratif, c'est qu'ils soient repr�sent�s par "quelque chose" qui est connu par le compilateur.
Cela peut �tre:
- une valeur num�rique enti�re connue comme une constante de compilation, par exemple au travers d'un code proche deOu cela peut �tre un type de donn�e (une structure), � ceci pr�s que, comme cela ne servira qu'� la compilation, il ne sert absolument � rien qu'il contienne des donn�es. Nous pourrons donc d�finir des structures vides pour repr�senter nos diff�rents tags, sous une forme proche de
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 enum Characteristics{ live, mana, strenght, agility, /*...*/ }; template <typename T, typename U, int Tag> struct MyStruct{ T x; U y; }; using live_infos = MyStruct<int, double, live>; using mana_infos = MyStruct<int, double, mana>; using strength_infos = MyStruct<int, double, strenght>; using agility_type = MyStruct<int, double, agility>;et nous obtiendront un r�sultat exactement �quivalent.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9 struct LiveTag{}; struct ManaTag{}; struct StrenghtTag{}; struct AgilityTag{}; using live_infos = MyStruct<int, double, LiveTag>; using mana_infos = MyStruct<int, double, ManaTag>; using strength_infos = MyStruct<int, double, StrenghtTag>; using agility_type = MyStruct<int, double, AgilityTag>;
L'�norme avantage des structures vides, c'est qu'il est tout � fait possible de rajouter un tag (et l'alias de type qui va avec pour les informations) � peu pr�s n'importe o� dans le code, sans avoir besoin d'aller modifier l'�num�ration, et donc de mieux respecter l'OCP.
Mais, comme rien n'est gratuit en ce bas monde, cet avantage pr�sente �galement l'inconv�nient de -- justement -- "�parpilller" les diff�rents tags dans le code; m�me s'il est "tout � fait possible" de les regrouper dans un fichier d'en-t�te unique![]()
A m�diter: La solution la plus simple est toujours la moins compliqu�e
Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
mon tout nouveau blog
C'est parfait merci beaucoup pour l'explication !!![]()
Partager