Bonjour � tous,
Alors pour la petite histoire, j'ai touch� � pas mal de langages informatiques. A la base j'�tais un peu du genre pro-java et le C++ me faisait pousser des boutons, mais je pense que la fac nous am�ne un peu � penser ce genre de choses... Enfin bref, dans un soucis de performances (ex�cution et m�moire) je suis pass� au C++ il y a un peu plus de 3 ans. � la base s'�tait surtout pour faire un petit test de performance et je dois dire que je suis franchement rest� sur le cul, surtout pour la m�moire o� j'ai vu la consommation fondre comme neige au soleil.
Le C++ r�ponds � mes attentes � ce niveau l� et en bonus j'ai de plus �t� extr�mement s�duit par la puissance des templates et les nouveaut�s du C++11. Sauf que depuis le d�but j'ai beaucoup de mal avec la biblioth�que standard. Non pas que je n'arrive pas � m'en servir ou que je ne la comprenne pas, mais je la trouve assez lourde � utiliser. Je pense clairement tout d'un point de vue orient� objet, design pattern, etc... et ce qui est propos� par la biblioth�que stantard ou boost ne me satisfait pas compl�tement. J'aime l'approche orient� objet mais aussi l'approche langage "fonctionnel" qu'apportent les lambdas avec C++11.
Du coup je me suis d�velopp� une petite biblioth�que durant mon temps libre. Le but est le suivant: gr�ce au C++11 simplifier un maximum ce que parfois la biblioth�que standard ou bien l'association avec boost prends plusieurs lignes � �crire, tout en gardant un code clair et parlant. Pour pr�senter rapidement l'approche (car la biblioth�que commence � devenir assez grosse, avec de nombreux concepts que je ne vais pas pr�senter ici), je vais prendre un exemple simple o� l'on souhaite manipuler un fichier texte et � r�cup�rer toutes les lignes qui contiennent des mots qui commencent par "bb", et pour finir afficher les lignes s�lectionn�es.
En C++ classique :
Avec ma biblioth�que :
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
24
25
26
27
28
29
30 std::ifstream file("MonFichier.txt"); std::vector<std::string> interesting_lines; if(file) { std::string line; boost::char_separator<char> separator(";"); while(std::getline(file, line)) { boost::tokenizer<boost::char_separator<char> > token(line,separator); boost::tokenizer<boost::char_separator<char> >::iterator word_iterator=token.begin(); while(word_iterator!=token.end()) { if(boost::starts_with( *word_iterator, "bb")) { interesting_lines.push_back(line); break; } ++word_iterator; } } file.close(); } else throw std::logic_error( "Impossible d'ouvrir le fichier" ); for(std::string line : interesting_lines) { std::cout << line << std::endl; }
Si certains connaissent Ruby, vous y aurez s�rement reconnu une claire influence, j'use et j'abuse des lambdas. Bref, c'est en fin de compte tr�s proche de ce que l'on peut faire avec un std::copy_if ou bien un std::any_of, mais il n'y a pas la gestion des pointeurs de d�but et de fin (que je trouve p�nible � �crire et � lire). En surchargeant les lambdas, je peux �galement faire :
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 oo::File file("monFichier.txt") oo::Vector<oo::String> interesting_lines; interesting_lines = file.collect_if([] (oo::String& line) { return line.split(";").is_any([] (oo::String& word) { return word.start_with("bb"); }); }); interesting_lines.each([](oo::String& line) { std::cout << line << std::endl; });
Ici nous ne prenons plus le probl�me ligne par ligne, mais phrase par phrase (donc s�par� par un point). En fait j'utilise ce syst�me car il s'av�re extr�mement flexible. Dans ce cas ci, j'ai deux classes abstraites IterableElement et CollectableElement qui impl�mentent les fonctions is_any() et collect_if() respectivement. Ces deux classes d�finissent une m�thode abstraite each() utilis�e par is_any() et collect_if() et qui doit �tre impl�ment�e dans la classe fille, et qui permet d'it�rer sur des �l�ments d'un type T (ici String et Sentence). Pour info, je pr�cise que IterableElement et CollectableElement poss�dent bien plus de fonctions, mais j'ai simplifi�.
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 oo::File file("monFichier.txt") oo::Vector<oo::String> interesting_lines; interesting_lines = file.collect_if([] (oo::Sentence& sentence) { return sentence.split(";").is_any([] (oo::String& word) { return word.start_with("bb"); }); }); interesting_lines.each([](oo::String& line) { std::cout << line << std::endl; });
-> Toute classe qui h�rite de IterableElement<T> et CollectableElement<T> et qui impl�mente la fonction each() pour l'�l�ment T pourra utiliser les lambas impl�ment�es dans les classes m�res
-> Du coup il est possible d'h�riter plusieurs fois d'une de ces classes avec un type diff�rent pour multiplier les possibilit�s.
Pour un exemple peut �tre plus concret, prenons un multigraphe (plusieurs ar�tes possibles entre deux sommets) non dirig� qui peut avoir des ar�tes color�s et des sommets color�s. Le probl�me est de supprimer tous les sommets bleus qui ont toutes leurs ar�tes connect�es qui sont rouges :
Inversement si l'on souhaite supprimer toutes les ar�tes rouges qui ont tous leurs sommets connect�s qui sont bleus :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11 oo::MultiGraph<oo::Color, oo::Color> g = fonctionQuiGenereMonGraphe(); g.remove_if([] (oo::MultiGraph::Vertex<oo::Color, oo::Color> vertex) { return (vertex.label() == oo::Color::Blue) && vertex.is_all([] (oo::MultiGraph::Edge<oo::Color, oo::Color> edge) { return edge.label() == oo::Color::Red; }); });
J'ai mes propres versions des containers de la biblioth�que standard : Vector, Set, List, Map que j'ai seulement encapsul� et enrichi des nouvelles m�thodes. Puis j'ai d'autres structures de donn�es plus complexes : Sequence, Graphe, MultiGraph, DirectedGraph, DirectedMultiGraph, Matrix, MapMatrix. Au niveau perf il faudrait que je fasse des benchmarks mais honn�tement je n'ai pas not� de grosses diff�rences � utiliser les lambdas. De plus lorsque l'on voit un objet oo::MultiGraph::Edge pour un graphe, on peut se dire que derri�re il y a beaucoup d'objets. En fait non, derri�re j'ai par exemple simplement une matrice d'adjacence et les objets sont simplement g�n�r�s � la vol�e pour la lambda et cela reste transparent pour l'utilisateur.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11 oo::MultiGraph<oo::Color, oo::Color> g = fonctionQuiGenereMonGraphe(); g.remove_if([] (oo::MultiGraph::Edge<oo::Color, oo::Color> edge) { return (edge.label() == oo::Color::Red) && edge.is_all([] (oo::MultiGraph::Vertex<oo::Color, oo::Color> vertex) { return vertex.label() == oo::Color::Blue; }); });
Ma question est que pensez vous d'un tel design ? Y voyez vous des inconv�nients ou bien avez vous des remarques ?
Je pr�cise que j'ai appris le C++ tout seul, ne me maltraitez pas trop svp.![]()
Partager