Entries for category NoteToMyself

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

Sun Nov 22 2009

Equivalent de ldconfig sous OSX

Y en n'a pas vraiment

Filed under MacNoob, NoteToMyself, Programming. 0 comment
$ man dyld
Sun Nov 22 2009

Equivalent de ldd sous OSX

Shared library dependencies

Filed under MacNoob, NoteToMyself, Programming. 1 comment
$ otool -L file
Tags ldd, osx, otool, shell