2009-12-11 17 views
6

Je dois appeler une méthode qui attend un pointeur de fonction, mais ce que je veux vraiment lui transmettre est un foncteur. Voici un exemple de ce que je suis en train de faire:Fonction de pointeurs vers les fonctions membres en C++

#include <iostream> 
#include "boost/function.hpp" 

typedef int (*myAdder)(int); 

int adderFunction(int y) { return(2 + y); } 

class adderClass { 
    public: 
    adderClass(int x) : _x(x) {} 
    int operator() (int y) { return(_x + y); } 

    private: 
    int _x; 
}; 

void printer(myAdder h, int y) { 
    std::cout << h(y) << std::endl; 
} 

int main() { 
    myAdder f = adderFunction; 

    adderClass *ac = new adderClass(2); 
    boost::function1<int, int> g = 
    std::bind1st(std::mem_fun(&adderClass::operator()), ac); 

    std::cout << f(1) << std::endl; 
    std::cout << g(2) << std::endl; 
    printer(f, 3); 
    printer(g, 4); // Is there a way to get this to work? 
} 

Je n'ai pas été en mesure de trouver un moyen d'obtenir la dernière ligne, imprimante (g, 4), de compiler. Y a-t-il un moyen de faire en sorte que cela fonctionne? Les seules choses dans mon contrôle sont la méthode "main" et la classe "adderClass".

Répondre

0

comme ceci:

template<typename AdderT> 
void printer(AdderT h, int y) { 
    std::cout << h(y) << std::endl; 
} 

En outre, vous n'avez pas besoin boost::function. Vous pouvez simplement faire:

adderClass ac(2); 
    std::cout << f(1) << std::endl; 
    std::cout << ac(2) << std::endl; 
    printer(f, 3); 
    printer(ac, 4); 
+0

Cela fonctionnerait, mais (j'ai oublié de mentionner), la méthode "imprimante" est dans le code que je ne peux pas changer. – JamieC

+0

Tout ce qui est sous mon contrôle est la méthode "main" et la classe "adderClass". – JamieC

0

Bien qu'une fonction boost se comporte comme un pointeur de fonction normal, il s'agit d'un type différent. Vous ne pouvez donc pas attribuer une fonction boost à un pointeur de fonction.

Dans votre code, vous pouvez simplement remplacer

typedef int (*myAdder)(int); 

avec

typedef boost::function1< int, int > myAdder; 

et tout fonctionnerait.

2

Ok, voici un autre essai:

class CallProxy 
{ 
public: 
    static adderClass* m_instance; 
    static int adder(int y) 
    { 
     return (*m_instance)(y); 
    } 
}; 

adderClass* CallProxy::m_instance = NULL; 


int main() { 
    myAdder f = adderFunction; 

    adderClass ac(2); 

    std::cout << f(1) << std::endl; 
    std::cout << ac(2) << std::endl; 
    printer(f, 3); 
    CallProxy::m_instance = &ac; 
    printer(CallProxy::adder, 4); 
} 

Le problème est que vous avez printer compilé comme ayant pour recevoir un pointeur de fonction et rien d'autre que vous devez envoyer un pointeur de fonction. Avec un pointeur de fonction, vous n'avez personne pour contenir votre instance. Donc, cette solution le fait en utilisant un membre de données statique.

Notez que cela rend ce code non sécurisé. Deux threads qui exécutent main en même temps peuvent mettre deux choses différentes dans m_instance.

+1

Ce n'est pas non plus re-entrant: si 'printer' appelle' main' vous avez des problèmes. Mais je pense que c'est le mieux que l'on puisse faire compte tenu des contraintes, du moins de façon portative. Pour les solutions non portables, vous pouvez par exemple générer du code à la volée. –

+0

@Steve Jessop: Tout ce qui appelle 'main()' provoque un comportement indéfini de toute façon (§3.6.1/2: "La fonction principale ne doit pas être utilisée (3.2) dans un programme.") –

+0

@Jerry Coffin - essayer de regarder au-delà des limites limitées de cet exemple idiot. – shoosh