Entries for tag c++

Thu Apr 08 2010

Boost Phoenix 2.0 tips

Lazy lazy evaluation + bind to overloaded member

Filed under C++, NoteToMyself, Programming. 0 comment

Quelques tips pour Boost.Phoenix2 glanés dans la sueur et dans le sang (dans la doc aussi).

Higher higher order function

On a vite fait d'imbriquer les algorithms de Phoenix, mais il ne faut pas oublier qu'ils sont déjà des higher order functions. Leur prédicats doivent être évalués de manière lazy et même lazy lazy si je puis dire.

Un code vaut mieux qu'un long schema à main levée. Dans ce qui suit, j'ai deux std::vector de int. Je veux afficher les éléments du premier vector qui ne sont pas dans le second. Un code à la con qui a juste valeur d'exemple. Dedans y est glissée une erreur grossière. Saurez-vous la trouver ? Votre compilo saura la trouver lui, et il se fera un plaisir de générer environ 50ko de message d'erreur :)

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/home/phoenix/scope/local_variable.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp>
#include <boost/spirit/home/phoenix/scope/let.hpp>
#include <boost/spirit/home/phoenix/container.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_algorithm.hpp>

int main()
{
    using boost::phoenix::arg_names::arg1;
    using boost::phoenix::local_names::_a;
    using boost::phoenix::ref;
    using boost::phoenix::let;
    using boost::phoenix::if_;
    using boost::phoenix::find_if;
    using boost::phoenix::end;
	
    std::vector<int> a;
    std::vector<int> b;
	
    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
	
    b.push_back(2);
	
    std::for_each(a.begin(), a.end(),
        let(_a = arg1)
        [
            if_(end(ref(b)) == find_if(ref(b), arg1 == _a))
            [
                std::cout << _a << std::endl
            ]
        ]
    );
	
    return 0;
}

Le problème est que find_if attend un prédicat, dont on pourrait penser qu'il est tout à fait correcte en tant que composite phoenix arg1 == _a. Mais le bloc du find_if est déjà un composite, autrement dit une higher order function. Son prédicat doit être évalué de manière lazy lazy et non pas lazy -tout court.

La solution est fournie par phoenix: le composite lambda va permettre de transformer le prédicat récalcitrant en une higher higher order function. Le tour est joué:

std::for_each(a.begin(), a.end(),
    let(_a = arg1)
    [
        // lambda[arg1 == _a]
        if_(end(ref(b)) == find_if(ref(b), lambda[arg1 == _a]))
        [
            std::cout << _a << std::endl
        ]
    ]
);

Bind to overloaded member function

Qui n'a jamais été tenté de binder à gogo avec phoenix, tellement c'est facile ? Le prob survient le jour où on tente désespérément de binder une fonction qui a des overloads. le compilo se plaint avec un message du genre bind(<unresolved overloaded function type>, ..25 lignes de types phoenix..).

Example. Je cherche à binder std::map<K,V>::find. On va prendre int pour K et V. m est une instance quelconque de ce type map:

typedef std::map<int, int> map_t;

bind(&map_t::find, ref(m), arg1);

Pas bon. map_t::find a plusieurs overloads. Le compilo ne sait pas lequel choisir. Il faut le guider, après tout, c'est nous les boss dans l'histoire!

Méthode one liner:

bind(static_cast<
        map_t::const_iterator (map_t::*)(int const&) const
     >(&map_t::find), ref(m), arg1);

On utilise ce bon vieux static_cast.

Autre méthode, passer par un pointer sur fonction membre:


map_t::const_iterator (map_t::*find_f)(int const&) const = &map_t::find;

bind(find_f, ref(m), arg1);

Ca fait son job. On n'en demande pas plus.

Conclusion

RAS

Wed Apr 07 2010

Un point sur les C++0x Core Language Features

Filed under C++. 0 comment

Le Visual C++ Team Blog vient de publier une table listant les features de C++0x C++11 qui seront disponibles dans Visual Studio 2010.

Le site de GCC met à disposition un document similaire pour son compilateur. Le wiki d'Apache propose également un tableau mettant en concurrence divers compilos.

Les variadic templates (pdf) ne seront donc pas supportées dans VS2010. C'est fort dommage, car elles font partie des features incontournables, et j'oserai même dire emblématiques, du prochain standard C++.

Naïf, peut être, candide, surement, gros noob (aussi), j'avais espéré que Microsoft finisse par les implémenter à temps pour la release de leur produit. Après tout, si on regarde la liste, VS2010 fournira une bonne part des grosses nouveautés, celles qui sont vraiment catchy, à commencer par les lambda expressions (pdf), les rvalue references ou encore, le must, les right angle brackets ;)

Fri Mar 19 2010

r8t, un moteur de template pour C++ à base de javascript

Google V8 inside

Filed under C++, Programming. 2 comments

L'idée de base, mais vraiment de base, consiste à clamer à qui veut bien l'entendre que JSON est un format idéal pour passer des données à un système de Vue, comprendre View, dans un MVC. Ce format a tout ce qu'il faut: simple, compact, expressif et connu de tous, ou presque.

Le constat de base, mais vraiment de base (oui vous savez), c'est qu'il y a très peu de systèmes de template pour C++ qui ont un penchant web, c'est à dire principalement orientés génération de HTML. Je ne sais pas pourquoi, peut être parce que tout le monde s'en fout ? ;) Toujours est-il que lorsque je me suis mis en recherche d'un tel système de template, pour des besoins perso, je n'ai rien trouvé d'autre que Clearsilver et google-ctemplate. Il me fallait un truc standalone et léger. J'aurai pu chercher un peu plus, mais je me suis arrêté là, pas vraiment convaincu.

C'est là que je me suis souvenu de l'idée de base: JSON. En fait ça tombait bien puisque j'utilisais déjà le moteur javascript V8 dans mon projet. Cet engine, initialement conçu par google pour le navigateur Chrome, est open source et son API est en C++. L'idée qui a commencé à émerger est la suivante:

  • On balance du "JSON" au système de template
  • La logique de présentation est controllée par javascript
  • Le système crache du text en retour (principalement du HTML)

Sympa. Reste plus qu'à implémenter ça.

Le JSON, expédié avec une technique à base de Boost.Variant récursif que j'ai présenté dans ce billet Simple modélisation de JSON en C++.

Le javascript qui controle la logique de présentation est embarqué dans les templates sous une forme proche d'un mix de Django et de la syntaxe alternative de php.

{% for (i in posts) : %}
  <div class="post">
    <h2>{%= posts[i].title %}</h2>
    ...
  </div>
{% end %}

Le principe c'est que tout ce qui est entre {% ... %} est grosso modo du javascript qui sera inchangé avant de le donner au moteur js. Une phase de parsing transforme le fichier de template (ou n'importe quel text) en une forme intermédiaire qui sera consumée par V8. Pour l'exemple ci-dessus, cela donne quelque chose proche de ceci:

for (i in posts) {__pr('  <div class="post">\n    <h2>');
__p(posts[i].title);__pr('</h2>\n    ...\n  </div>\n');};

Le parser est écrit avec la librairie Boost.Spirit Classic. __p() pour "print" et __pr() pour "print raw" sont des fonctions javascript dont l'implémentation est en C++ et qui permettent de controller la sortie textuelle finale, par exemple en appliquant des filtres d'échappement automatique pour du HTML. Ces filtres sont inspirés des modifiers de google-ctemplate. Du genre {%:h:s= comment %} pour un filtre h qui échappe du HTML et un autre s qui permet de wrapper des snippets entre des éléments <pre>.

Ce qui est sympathique c'est qu'il est possible de transformer des sources javascript textuelles en un byte code propre à V8. C'est dans l'API. On peut donc mettre en cache des templates pre compilées, un peu comme le fait APC pour php, mais ça dépote encore plus! J'avais effectué quelques benchmarks qui laissaient penser que ce moteur de template à base de V8 était plus véloce que php+APC. Il faudrait que je mesure ça plus sérieusement.

A vrai dire ce projet de système de template a été codé à l'arrache courant novembre 2009. Un simple proof of concept à l'origine. Les dernières librairies de Boost notamment Spirit 2 (ça tue!), Phoenix 2 et Fusion 2 (OK, beaucoup de 2) m'ont donné envie de réécrire un tel système. J'héberge le truc sur github. Je lui ai donné le joli nom de r8t, réunion de rat et V8. Pour l'instant, c'est succinct. Pourquoi rat? Parce que ;)

Thu Dec 24 2009

Bilan du blog pour 2009

Filed under Blog, Vrac. 0 comment

2009 s'achève. Encore une année passée à fond la caisse. Rien vu passé en fait. Fin d'année rime avec bilan et bêtisier (et prévisions astrologiques, mais on n'en a rien à foutre). Ok. RAS pour l'intro.

Au mois de février, ou un truc du genre, je m'étais juré d'ouvrir un blog. Je m'étais dit la même chose l'année précédente et l'année d'avant aussi. Bref, y a quelque chose qui a sérieusement merdé en 2009 pour que ce blog puisse enfin voir le jour.

Ce qui a déconné grave en 2009

Tout a commencé avec l'envie inexpliquée de me choper un VPS. Après investigations, mon choix s'est porté sur Linode. A postériori, ce choix n'était pas mauvais puisque leurs plateformes Xen déchirent leur race. Bon, j'aurais pu faire l'erreur de me trouver piéger quant aux choix de l'OS, du kernel et tout, mais non, il a fallu que Slackware soit dispo. Franchement là je commençais à me dire "putain avec ces conneries tu vas finir par l'ouvrir ton blog". Je vous raconte pas les boules.

En parallèle, la nécessité de plus en plus pressante de changer de laptop se faisait.. de plus en plus pressante. En gros, je lorgnais sur des ASUS de gamers, de quoi assouvir mes envies de meurtres et pouvoir y foutre sereinement une distrib linux en dual boot. Pourquoi ASUS, pourquoi un PC d'ailleurs ? C'est une excellente question, mais j'ai autre chose à foutre faire que d'y répondre (j'ai déjà mis foutre deux phrases plus haut). Non, vraiment, la seule chose dont j'étais sur, c'est que MOI vivant, JAMAIS je ne claquerais 1500 euros dans une arnaque de MacBook. Encore une heure avant de me rendre sur l'App Store un soir et y claquer frénétiquement juste à peine moins de 1500 euros tel un maniaco compulso-dépressif, j'aurais maintenu mes positions sous la tortures. Heureusement que je suis blindé de thunes.

Essayons de bien comprendre: à ce moment là de l'année, rien ne se passait comme prévu. Putain j'allais quand même pas finir par installer Wordpress ou Dotclear. Si près du but, sans la moindre embuche, c'est pas possible ou quoi. Y a pas moyen.

Une solution de secours: virer LAMP

Et remplacer cette stack par LEMC++. Une solution de secours à la RACHE, nous sommes d'accord. Au moins avec un peu de chance ça devrait pouvoir ruiner ce qu'il restait de 2009, d'autant plus que je m'étais dis "hum hum, tu vas te remettre à la guitare".

Pas le temps de placer 3 accords de 7ième mineur, que déjà mon VPS compile GCC trunk plus rapidement que le Mac. Et les gars de Linode ne bronchent pas. Il ne s'agit pourtant que d'un plan 360. Moi je vous dis, ça pue... d'autant plus que les concours de circonstances fortuites et malheureuses s'enchainent:

Consternant. Et ce n'est pas un ApacheBench qui viendra contrecarrer cet état de fait. Oui, c'est affligeant, mais cette daube encaisse plus de 5000 requêtes par seconde.

Server Software:        nginx/0.8.27
Server Hostname:        blog.runpac.com
Server Port:            80

Document Path:          /
Document Length:        21134 bytes

Concurrency Level:      10
Time taken for tests:   0.173 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      21271000 bytes
HTML transferred:       21134000 bytes
Requests per second:    5779.68 [#/sec] (mean)
Time per request:       1.730 [ms] (mean)
Time per request:       0.173 [ms] (mean, across all concurrent requests)
Transfer rate:          120058.15 [Kbytes/sec] received

Sur du 360...

$ free -m
             total       used       free     shared    buffers     cached
Mem:           348         77        271          0         17         42
-/+ buffers/cache:         17        330
Swap:          255          0        255

Mais qu'est-ce qui a bien pu déconner ??

Sauvé par les stats de visites

Manquerait plus que le site soit fréquenté! Après un mois et demi d'existence, seul une poignée d'inconscients (autres que les déferlantes de bots google et baidu) atterrissent ici. Franchement, au début j'ai eu peur. Déjà que je me fais chier à blogger en français EXPRES. Par chance vous n'êtes pas plus de 20 peulés chaque jour à perdre votre temps ici.

Faite gaffe quand même. 2009 n'est pas fini.