2009-04-17 3 views
2

J'ai une fonction générique:Problème boost :: imbrication lambda :: bind-s

void ImageAlbum::ExpressButtonPressed(
    boost::function< 
     void (
      thumb::PhotoPrintThumbnail*, 
      thumb::PhotoPrintFormat, 
      thumb::PhotoPrintQuantity 
     ) 
    > memberToCall 
) { 
    ... 

    BOOST_FOREACH(thumb::PhotoPrintThumbnail *pThumbnail, m_thumbs.GetSelected()) { 
    memberToCall(
      pThumbnail, 
      m_expressSel.GetSelectedFormat(), 
      m_expressSel.GetSelectedQuantity() 
     ); 
    } 

    ... 
} 

je peux appeler avec succès:

ExpressButtonPressed(boost::bind(&thumb::PhotoPrintThumbnail::AddQuantity, _1, _2, _3)); 

Ensuite, au lieu d'ajouter une quantité d'un certain format à une vignette, je dois les remplacer tous avec un seul format. Plus précisément, avec une liste de 1 élément, comme ça:

ExpressButtonPressed(
    boost::lambda::bind(
     &thumb::PhotoPrintThumbnail::SetFormats, 
     _1, 
     boost::lambda::bind(
      boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormats>(), 
      1, 
      boost::lambda::bind(
       boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormat>(), 
       _2, 
       _3 
      ) 
     ) 
    ) 
); 

qui se traduit par « boost/lambda/détail/actions.hpp (96): erreur C2665: « boost :: lambda :: function_adaptor :: apply ': aucune des deux surcharges ne peut convertir tous les types d'arguments ".

Qu'est-ce que je fais mal ici?

BTW

class PhotoPrintThumbnail { 
public: 
... 
    typedef std::pair<PhotoPrintFormat, PhotoPrintQuantity> LoadedFormat; 
    typedef std::list<LoadedFormat> LoadedFormats; 
    void SetFormats(const LoadedFormats &formats); 
+3

Je frémis en pensant que je devrais maintenir votre code un jour ..;) –

+0

Eh bien, ne frémit pas trop, c'est juste mon essayant tout ce truc lambda pour la première fois. A été intéressé jusqu'où je peux le pousser. Très probablement, ne sera jamais commis. –

+0

Quel est le message d'erreur, en particulier les types et leurs paramètres de modèle? – jpalecek

Répondre

4

Y a-t-il des #include boost/bind.hpp dans votre code lambda? Cela provoquerait une utilisation non qualifiée des espaces réservés (_1, _2, etc) pour résoudre ceux définis par Boost.Bind, et ceux-ci ne se mélangent pas bien avec Boost.Lambda.

Réécrire votre code pour utiliser explicitement boost :: lambda :: _ [1,2,3] au lieu des noms non qualifiés compile bien sur mon installation de VC 7.1.

0

Je ne sais pas quelle version de Boost ou quel compilateur utilisez-vous. Avec boost 1.37 et VS2005 je peux obtenir la même erreur. Je soupçonne qu'il se peut qu'une erreur au cœur de l'extension de modèle provoque un problème SFINAE.

Par exemple en prenant l'expression la plus profonde sur:

boost::function< 
    PhotoPrintThumbnail::LoadedFormat (
      PhotoPrintFormat, 
      PhotoPrintQuantity 
    ) 
> func = boost::lambda::bind 
       (boost::lambda::constructor<PhotoPrintThumbnail::LoadedFormat>() 
       , _1 
       , _2 
       ); 

Cela semble ok pour moi ne encore aussi, mais avec un:

std :: paire < _Ty1, _Ty2> :: paire »: aucune des trois surcharges n'a pu convertir tous les types d'argument

erreur.

Bien sûr, vous pouvez simplement utiliser:

void func 
(PhotoPrintThumbnail* ppt 
, const PhotoPrintFormat& ppf 
, const PhotoPrintQuantity& ppq 
) 
{ 
    ppt->SetFormats (PhotoPrintThumbnail::LoadedFormats (1, PhotoPrintThumbnail::LoadedFormat (ppf, ppq))); 
} 

ExpressButtonPressed (func); 

qui est plus claire et compile.

0

Je pense que lors de la première liaison, il faut lier l'objet construit (traduite à partir de la deuxième liaison) en tant que premier paramètre de la méthode (il devrait être l'adresse de l'objet construit):

ExpressButtonPressed(
    boost::lambda::bind(
     &thumb::PhotoPrintThumbnail::SetFormats, 
     boost::lambda::bind(
       boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormats>(), 
       1, 
       boost::lambda::bind(
         boost::lambda::constructor<thumb::PhotoPrintThumbnail::LoadedFormat>(), 
         _2, 
         _3 
       ) 
     ), 
     _1 
    ) 
); 

I n'a pas essayé de compiler le code. Un autre problème possible est que le deuxième foncteur de liaison peut renvoyer l'objet construit par valeur, et la première liaison requiert un pointeur sur l'objet (comme ce pointeur), vous avez donc toujours besoin d'un pointeur comme premier paramètre lié pour SetFormats.