2010-04-30 11 views
1

Je voudrais appeler un membre via lambda :: bind. Malheureusement, j'ai deux membres avec le même nom mais différents types de retour. Existe-t-il un moyen d'aider lambda :: bind à déduire le bon type de retour pour un appel de fonction membre? (Bind fonctionne très bien avec déduction de type retour explicite)boost lambda :: bind type de retour sélection

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <boost/bind.hpp> 
#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/bind.hpp> 

using namespace std; 
using namespace boost; 

struct A 
{ 
    A (const string & name) : m_name(name) {} 

    string &  name()   { return m_name; } 
    const string & name() const { return m_name; } 

    string m_name; 
}; 

vector<A> av; 

int main() 
{ 
    av.push_back (A ("some name")); 

    // compiles fine 
    find_if(av.begin(), av.end(), bind<const string &>(&A::name, _1) == "some name"); 

    // error: call of overloaded 'bind(<unresolved overloaded function type>, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&)' is ambiguous 
    find_if(av.begin(), av.end(), lambda::bind(&A::name, lambda::_1) == "some name"); 

    return 0; 
} 

Répondre

1

Les différents types de retour sont un hareng rouge. Le problème est avec la surcharge de const de la méthode (c'est-à-dire que vous auriez le même problème quel que soit le type de retour relatif). Ce problème est documenté et here, et en utilisant le formulaire spécifié par le type de retour est not the recommended solution (fonctionnera la plupart du temps, sauf une version de MSVC). Le problème est que le fait de prendre l'adresse d'une fonction membre surchargée (soit surc surchargée, soit surchargée de paramètre) est ambiguë, donc certaines informations supplémentaires sont nécessaires. La solution consiste à lancer le pointeur de fonction, ce qui permet au compilateur de savoir exactement quelles sont les fonctions surchargées que vous voulez. La façon la plus simple de le faire est de typer les types de pointeur de fonction, sinon les lignes un peu méchant. Voici un exemple avec votre code (gcc compile propre 4.3.4):

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <boost/bind.hpp> 
#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/bind.hpp> 

using namespace std; 
using namespace boost; 

struct A 
{ 
    A (const string & name) : m_name(name) {} 

    string &  name()   { return m_name; } 
    const string & name() const { return m_name; } 

    string m_name; 
}; 

vector<A> av; 

//function pointer for non-const version 
typedef string& (A::*NameFuncType)(void); 

//function pointer for const version 
typedef const string& (A::*NameConstFuncType)(void) const; 

int main() 
{ 
    av.push_back (A ("some name")); 

    //'correct' way to call const version w/ boost::bind 
    find_if(av.begin(), av.end(), 
    bind(static_cast<NameConstFuncType>(&A::name), _1) == "some name" 
); 

    //call for non-const version w/ boost::lambda::bind 
    find_if(av.begin(), av.end(), 
    lambda::bind(static_cast<NameFuncType>(&A::name), lambda::_1) == "some name" 
); 

    return 0; 
} 
1

Pour la documentation

« Le type de retour de la foncteur lambda créée par l'expression de liaison peut être donnée en tant que paramètre de modèle spécifié explicitement, comme dans le exemple suivant:

bind (cible fonction, liste de liaison argument) »

Bougez donc la même chose que vous avez fait avec boost: bind.

find_if(av.begin(), av.end(), lambda::bind<const string &>(&A::name, lambda::_1) == "some name"); 

P.S. non testé

+0

Vous venez de le rappeler le vrai problème :) Il y a un moyen de passer outre le type de retour dans lambda :: boost, mais il ne fonctionne pour l'expression lambda pas pour la liaison. voir: lambda :: ret (e) dans la référence. Malheureusement dans la situation actuelle, il n'est pas applicable ... – psaghelyi