Pointeur de méthode?

Le
Gégé
Salut,

J'aimerais savoir s'il est possible de créer un pointer non pas de
fonction mais de méthode ( autre que statique )
Ci-après un exemple qui renvoie une erreur de compilation pour "a.f1"

error C2276: '&' : illegal operation on bound member function
expression

Merci
G


class A
{

public :

double f1( double x )
{
return x * x;
}

static double f2( double x )
{
return x * x;
}

A(){}
~A(){}
};

double f3( double x )
{
return x * x;
}

int main( void )
{
A a;
double (*h1)( double ) = &a.f1;
double (*h2)( double ) = &A::f2;
double (*h3)( double ) = &f3;

}
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Jean-Marc Bourguet
Le #18507411
Gégé
Salut,

J'aimerais savoir s'il est possible de créer un pointer non pas de
fonction mais de méthode ( autre que statique )
Ci-après un exemple qui renvoie une erreur de compilation pour "a.f1"

error C2276: '&' : illegal operation on bound member function
expression



Oui, mais un pointeur vers fonction membre n'est pas un pointeur vers
fonction, il faut l'appeler avec un objet. Remplace ton main() par:

int main( void )
{
A a, *p = &a;
double (A::*h1)( double ) = &A::f1;
double (*h2)( double ) = &A::f2;
double (*h3)( double ) = &f3;

(a.*h1)(1.0);
(p->*h1)(1.5);
(*h2)(2.0);
(*h3)(3.0);
}

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Gégé
Le #18515881
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...
Bertrand
Le #18518001
Gégé wrote:
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



C'est moche, mais (à ma connaissance) le seul moyen d'y arriver est le
suivant:

A* a;

double a_f1_callback( double d1, double d2 )
{
// devrait peut-être vérifier la validité de a?
return a->f1( d1, d2 );
}

void quelque_part()
{
A a1;
A a2;

a = &a1;
libfunction( x, a_f1_callback ); // appel avec a1

a = &a2;
libfunction( x, a_f1_callback ); // appel avec a2
}

si cela doit s'exécuter dans un contexte multi-thread, il faut alors
protéger a pendant le temps de l'exécution de libfunction.

je suppose que f1 est en fait une méthode const, donc A const* a devrait
faire l'affaire.

--
Bertrand
Gégé
Le #18519291
Effectivement c'est une piste !
Mais comme souligné ca va être un peu sale à intégrer dans mon proj et.

Je pense que je vais plutot renverser le pb :
* au lieu que la fonction de la lib se servir de la méthode
* je vais utiliser la méthode pour se servir de la fonction de lib

Je vais perdre en généricité, mais bon ca sera plus clean

Merci encore pour toutes ces réponses
pjb
Le #18522971
Gégé
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



class Class {
public:
virtual double membre(double x,double y);
};


Class* c=new Class;
double x=3.14;

libfunction(x,boost::bind(&Class::membre,c,_1,_2));


--
__Pascal Bourguignon__
Michael DOUBEZ
Le #18526331
Pascal J. Bourguignon wrote:
Gégé
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



class Class {
public:
virtual double membre(double x,double y);
};


Class* c=new Class;
double x=3.14;

libfunction(x,boost::bind(&Class::membre,c,_1,_2));



Je serais surpris que boost::function<void,double,double> se dégrade en
void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.

--
Michael
pjb
Le #18530231
Michael DOUBEZ
Pascal J. Bourguignon wrote:
Gégé
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...


class Class {
public:
virtual double membre(double x,double y);
};
Class* c=new Class;
double x=3.14;
libfunction(x,boost::bind(&Class::membre,c,_1,_2));



Je serais surpris que boost::function<void,double,double> se dégrade
en void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.



Oops, j'ai tellement l'habitude de travailler avec boost::function que
je n'ai pas remarqué qu'on voulait une simple fonction C...

Il reste une possibilité, pour le faire automatiquement, c'est
d'utiliser une bibliothèque comme ffcall ou llvm pour générer un
tramplin. C'est quelque chose qu'on pourrait ajouter à boost...

boost::trampoline<double(*)(double,double)>(boost::bind(&Class::membre,c,_1,_2))

--
__Pascal Bourguignon__
Michael DOUBEZ
Le #18531081
Pascal J. Bourguignon wrote:
Michael DOUBEZ
Pascal J. Bourguignon wrote:
Gégé
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...


class Class {
public:
virtual double membre(double x,double y);
};
Class* c=new Class;
double x=3.14;
libfunction(x,boost::bind(&Class::membre,c,_1,_2));


Je serais surpris que boost::function<void,double,double> se dégrade
en void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.



Oops, j'ai tellement l'habitude de travailler avec boost::function que
je n'ai pas remarqué qu'on voulait une simple fonction C...

Il reste une possibilité, pour le faire automatiquement, c'est
d'utiliser une bibliothèque comme ffcall ou llvm pour générer un
tramplin. C'est quelque chose qu'on pourrait ajouter à boost...

boost::trampoline<double(*)(double,double)>(boost::bind(&Class::membre,c,_1,_2))



C'est une idée mais ce serait limité à gcc et VC++.

L'idéal aurait été que le standard supporte la création de fonctions à
la volée ou que les lambdas puisses se traduire en tant que thunks. Un
volontaire ? :)

--
Michael
Gégé
Le #18539421
Bon, j'ai peut etre une solution en passant par des struct et des void
*

struct v_params
{
double (*f)( double k, void * p);
void * p;
};

struct v1_params
{
double v;
};

double v1_func( double x, void * p )
{
v1_params v1 = *( v1_params*) p;
return v1.v + x;
}

class A
{

public:

virtual v_params * v() = 0;
A(){}
~A(){}

};

class A1 : public A
{
public:
v_params * v()
{
v1_params * v1 = new v1_params;
v1->v = 2;

v_params * vp = new v_params;
vp->f = &v1_func;
vp->p = v1;

return vp;
}

A1(){}
~A1(){}
};

int main()
{
A * a = new A1();
v_params * v = a->v();
double x = v->f( 55, v->p );

return 0;
}

Qu'en dites-vous?
Michael DOUBEZ
Le #18555821
Gégé wrote:
Bon, j'ai peut etre une solution en passant par des struct et des void
*

struct v_params
{
double (*f)( double k, void * p);
void * p;
};

struct v1_params
{
double v;
};

double v1_func( double x, void * p )
{
v1_params v1 = *( v1_params*) p;
return v1.v + x;
}

class A
{

public:

virtual v_params * v() = 0;
A(){}
~A(){}

};

class A1 : public A
{
public:
v_params * v()
{
v1_params * v1 = new v1_params;
v1->v = 2;

v_params * vp = new v_params;
vp->f = &v1_func;
vp->p = v1;

return vp;
}

A1(){}
~A1(){}
};

int main()
{
A * a = new A1();
v_params * v = a->v();
double x = v->f( 55, v->p );

return 0;
}

Qu'en dites-vous?



Que ça ne résoudpas le problème tel que je l'ai compris. Le but étant de
passer un void (*)(double,double) en paramètre d'une bibliothèque en vue
d'une utilisation ultérieure; le souhait serait d'utiliser un appel à un
objet et celade façon paramètrablle. A moins d'avoir un moyen de
contraindre les paramètres qu'il lui seront passés, je ne voit pas
comment lui passer une structure.

Quand je fait un programme avec des callbacks en C, j'ajoute toujours un
void* optionnel stocké avec le callback (set/get_context). C'est dommage
qu'il n'y ait pas d'équivalent ici.

--
Michael
Publicité
Poster une réponse
Anonyme