2010-08-30 32 views
2

Je dois passer la fonction au pointeur. Pour ce faire, j'utilise boost :: function. La fonction qui attrape le pointeur est surchargée pour différentes signatures. Par exemple:Pointeurs vers les fonctions

void Foo(boost::function<int()>) { ... } 
void Foo(boost::function<float()>) { ... } 
void Foo(boost::function<double()>) { ... } 

Maintenant, je veux passer un peu de pointeur méthode de classe il:

class test 
{ 
    public: 
     float toCall() { }; 
}; 

class Wrapper 
{ 
    Wrapper() { 
    test obj; 
    Foo(boost::bind(&test::toCall, this)); 
    } 
}; 


error: no matching function for call to ‘Foo(boost::_bi::bind_t<float, boost::_mfi::mf0<float, test>, boost::_bi::list1<boost::_bi::value<Wrapper*> > >)’ 
    note: candidates are: Foo(boost::function<float()>&) 

Répondre

6

Nonono cela ne peut pas fonctionner. Parce que boost::function<...> a un constructeur basé sur un modèle pour accepter tous les types. La compatibilité avec la signature d'appel est vérifiée plus tard. La résolution de surcharge ne peut pas résoudre cela.

Aussi, je pense que vous voulez passer &obj au lieu de this. Essayez de convertir explicitement:

Foo(boost::function<float()>(boost::bind(&test::toCall, &obj))); 

Ceci est tout à fait laid si vous voulez donc d'introduire un typedef

void Foo(FloatHandler) { ... } 
... 
FloatHandler f(boost::bind(&test::toCall, &obj)); 
Foo(f); 

Ou finalement, vous pourriez faire Foo un modèle qui accepte ne importe quel type appelable T. Je soupçonne que c'est peut-être le plus simple, parce que dans le cas général, je soupçonne que vous ne savez pas à quoi vous devez vous lancer. Et que diriez-vous des gens qui veulent retourner un std::complex<>. Donc ...

template<typename T> 
void Foo(T) { ... } 
... 
Foo(boost::bind(&test::toCall, &obj)); 

Espérons que cela aide.

1

boost::bind ne retourne pas un objet boost::function. Il retourne un objet de type non spécifié pouvant être utilisé en tant que foncteur avec le nombre correspondant de paramètres.

Alors que boost::function peut être construit par conversion à partir du résultat de boost::bind, la résolution de surcharge dans ce cas est "trop ​​complexe" pour C++. (Supprimé mon mauvais exemple qui n'a pas vraiment illustré le bon problème).

+0

Pour la fonction Boost, le scénario est encore plus mauvais que cela. C'est comme 'template struct A {template A (U); }; 'now, * that * me semble insoluble xD Notez que vous pouvez * convertir * si vous n'aviez qu'une seule fonction. La difficulté est de * comparer * deux de ces séquences de conversion. Dans le cas de boost :: function, c'est carrément impossible, et dans votre cas, cela pourrait être possible, mais c'est trop compliqué pour les over-res. –

+0

@Johannes Schaub: Vous avez raison. Mon exemple illustrait un problème complètement différent: l'ambiguïté au lieu de "l'insoluble" :) – AnT

2

Dans la ligne

Foo(boost::bind(&test::toCall, this)); 

this est de type Wrapper. Mais la liaison ne peut pas trouver une méthode toCall dessus.

est ici une version fixe-up (complet, compile sur g ++ 4.3.2) qui est probablement ce que vous essayez de faire:

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

void Foo(boost::function<int()>) {} 
void Foo(boost::function<float()>) {} 
void Foo(boost::function<double()>) {} 

struct test { 
    float toCall() {return 0.0f;} 
}; 

int main(int,char**) { 
    test obj; 
    boost::function<float()> tgt=boost::bind(&test::toCall,obj); 
    Foo(tgt); 
    return 0; 
} 

Comme les notes de réponse de AndreyT, le type de retour de bind est. .. un peu bizarre, d'où la coercition explicite à un type de fonction approprié.