2009-06-07 5 views
2

Compte tenu de ces deux struct:cartographie d'un struct contenu avec boost

struct point { 
    int x,y; 
}; 

struct pinfo { 
    struct point p; 
    unsigned long flags; 
}; 

Et une fonction, qui change un point:

void p_map(struct point &p); 

Est-il possible d'utiliser l'amplification (par exemple boost :: bind ou boost :: lambda) pour créer une fonction équivalente avec:

void pi_map(struct pinfo &pi) { p_map(pi.p); } 

-edit: mise à jour pour additiona l information:

L'intention originale de cette fonction était de l'utiliser dans for_each. Par exemple donné cette fonction:

void p_map(struct point &p) 
{ 
    p.x += 1; 
    p.y += 1; 
} 

Je pourrais écrire:

void foreach(std::vector<struct pinfo> &pi_vec) 
{ 
    for_each(pi_vec.begin(), pi_vec.end(), pi_map); 
} 

Comme il a été suggéré dans une réponse, il est possible aux variables membres liées avec boost :: lambda, et de créer une version for_each autre:

void foreach2(std::vector<struct pinfo> &pi_vec) 
{ 
    boost::function<void (pinfo&)> pi_map2 = bind(&p_map, bind(&pinfo::p, _1)); 
    for_each(pi_vec.begin(), pi_vec.end(), pi_map2); 
} 

Mon problème avec cette approche est que gcc (v 4.3.2.) n'inline pas fonctions pi_map et p_map pour la version foreach2.

Le code x86 généré pour la fonction foreach1 est:

0000000000400dd0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)>: 
    400dd0:  48 8b 57 08   mov 0x8(%rdi),%rdx 
    400dd4:  48 8b 07   mov (%rdi),%rax 
    400dd7:  48 39 c2   cmp %rax,%rdx 
    400dda:  74 14    je  400df0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)+0x20> 
    400ddc:  0f 1f 40 00   nopl 0x0(%rax) 
    400de0:  83 00 01   addl $0x1,(%rax) 
    400de3:  83 40 04 01   addl $0x1,0x4(%rax) 
    400de7:  48 83 c0 10   add $0x10,%rax 
    400deb:  48 39 c2   cmp %rax,%rdx 
    400dee:  75 f0    jne 400de0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)+0x10> 
    400df0:  f3 c3    repz retq 

qui met en œuvre le for_each, sans faire appel à toutes les fonctions. De l'autre côté, le code généré pour le foreach2 est plus compliqué, en raison des optimisations , et ne semble pas (semble) aligner les fonctions de mappage. Cependant, ce problème semble être plus philosophique que pratique avec les processeurs de bureau modernes, car (curieusement) les performances sur ma machine est similaire pour les deux versions.

Répondre

6

Vous pouvez le faire avec boost :: lambda, member variables can be bound avec bind les mêmes fonctions membres de manière sont:

#include <boost/function.hpp> 
#include <boost/lambda/bind.hpp> 

using namespace boost::lambda; 

boost::function<void (pinfo&)> pi_map = bind(&p_map, bind(&pinfo::p, _1)); 
+0

grand +1. Très joli bijou caché. –

+0

Salut, Merci pour votre réponse! J'ai modifié ma question initiale pour ajouter quelques informations sur cette approche. – ynimous