Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Peter Strb » Tue, 28 Feb 2006 20:10:25


"Lionel Reynaud" < XXXX@XXXXX.COM > wrote in



Legal standard c++

#include <stdio.h>
//-----------------------------------------------------------------------

class Calcul
{
private:
double Valeur;
double Facteur;
protected:
double DoFacteur(double val);
public:
Calcul(double v);
double Resultat(void);
};

double somme(Calcul *c, double ((Calcul::*Fonction)(double)), int n)
{
double result = 0;
for (int i=0;i<n;i++)
result += (c->*Fonction)(i);
return result;
}

Calcul::Calcul(double v)
{
Facteur = v;
Valeur = 10.0;
}

double Calcul::DoFacteur(double val)
{
return Facteur*val;
}

double Calcul::Resultat(void)
{
Valeur = somme(this, &Calcul::DoFacteur, 10);

return Valeur;
}

int main(int argc, char* argv[])
{
Calcul *C = new Calcul(5);

printf("R = %f\n",C->Resultat());

delete C;

return 0;
}
//-----------------------------------------------------------------------
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Tue, 28 Feb 2006 20:26:27

Hi, i have i problem when i try to pass a function of a class as a parameter
of a function.

An example is more clear than a long speech :
//---------------------------------------------------------------------------
#include <stdio.h>
//---------------------------------------------------------------------------

double somme(double (*Fonction)(double), int n)
{
double result = 0;
for (int i=0;i<n;i++)
result += Fonction(i);
return result;
}

class Calcul
{
private:
double Valeur;
double Facteur;
protected:
double DoFacteur(double val);
public:
Calcul(double v);
double Resultat(void);
};

Calcul::Calcul(double v)
{
Facteur = v;
Valeur = 10.0;
}

double Calcul::DoFacteur(double val)
{
return Facteur*val;
}

double Calcul::Resultat(void)
{
Valeur = somme(DoFacteur,10);

return Valeur;
}

int main(int argc, char* argv[])
{
Calcul *C = new Calcul(5);

printf("R = %f",C->Resultat());

delete C;

return 0;
}
//---------------------------------------------------------------------------


How can i solve this problem ?

Thanks,
Lionel

 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Andrue Cop » Tue, 28 Feb 2006 21:27:14

Firstly I would recommend using a typedef for this:


typedef double (*TFonction)(double);

This will help clarify your code.

But the actual problem is that you are trying to pass a pointer to a
virtual function. This is difficult because since it's virtual it has
to have a 'this' pointer. When called normally 'this' is passed to it
as a hidden argument. When you're passing around function pointers they
normally only consist of one pointer (to the function itself) and
'this' is unavailable.

There are at least three solutions to this that I can think of:

1.
Look up _closure in the online help and work out how to use it. The
problem with this is that's a Borland extension and therefore not
portable. I believe that such a thing now exists or is under
consideration for the C++ standard but I'm not sure. Either way it
isn't part of Builder AFAIK.

2.
Implement 'this' handling yourself:

typedef double (*TFonction)( void * Instance,
double Dbl );

double Fonction( void * Instance,
double Dbl )
{
return static_cast<Calcul *>( Instance )->Fonction( Dbl );
}

double somme( void * This,
TFonction Fonction,
int n)
{
double result = 0;
for (int i=0;i<n;i++)
result += Fonction( This, i );
return result;
}

double Calcul::Resultat(void)
{
Valeur = somme( this, DoFacteur, 10);

return Valeur;
}

int main(int argc, char* argv[])
{
Calcul C( 5 ); // Why put it on the heap? Use the stack instead.

printf("R = %f",C.Resultat());

return 0;
}

This would be my preferred solution (with a little more tidying up). It
can tolerate recursion and is even thread-safe. It does however assume
that you can define the function pointer. If you can't then you have to
use the more ugly static version:

typedef double (*TFonction)(double);

Calcul * Instance; // This needs to be initialised FIRST!
double Fonction( double Dbl )
{
return Instance->Fonction( Dbl );
}

double somme( void * This,
TFonction Fonction,
int n)
{
Instance=This;

double result = 0;
for (int i=0;i<n;i++)
result += Fonction(i);
return result;
}

But this is not thread-safe and only recursion tolerant when there is
one instance at a time.

3.
There may be something Boost that will help.

You'll notice that I put the Calcul instance on the stack. This should
be the preferred place to put it. That way it gets cleaned up
automatically when the function ends. Most classes can go on the heap
but those that can't (such as VCL components) can gain the same
advantage by using std::auto_ptr

int main(int argc, char* argv[])
{
std::auto_ptr<Calcul> C( new Calcul( 5 ) );

printf("R = %f",C->Resultat());

return 0;
}
--
Andrue Cope [TeamB]
[Bicester, Uk]
http://www.yqcomputer.com/
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Andrue Cop » Tue, 28 Feb 2006 21:32:22


Cool - you learn something new every day :)

--
Andrue Cope [TeamB]
[Bicester, Uk]
http://www.yqcomputer.com/
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Tue, 28 Feb 2006 22:38:11

Many thanks to Peter and Andrue for their prompt responses ;)
I learn many thinks.

Lionel
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Wed, 01 Mar 2006 00:21:30

Now i have another problem. I my real problem, i can't modify the prototype
of the function "somme" because there come from a library.

Is a solution to make a "wrapper" around the function "somme" in my class ?




XXXX@XXXXX.COM ...
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Chris Uzda » Wed, 01 Mar 2006 00:40:22

"Lionel Reynaud" < XXXX@XXXXX.COM > writes:


If you need to make a free-standing function that knows to call a
member function of a given object, you will have some trouble. You'll
either need to make a global variable (to hold the object's address on
which you'll call the member), but that's not a good solution in
multi-threaded environments or for re-entrancy.

--
Chris (TeamB);
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Andrue Cop » Wed, 01 Mar 2006 01:28:18


I don't think so. See my second example.

There are things that you could do to tighten up that code but it
remains a 'dangerous' solution.

Is your application likely to have multiple 'Calcus' objects
instantiated at the same time? Is multi-threading an issue? It
shouldn't be too hard to at least detect such situations and reject
them back to the caller. A mutex or singleton class would do that.

http://www.yqcomputer.com/

You could probably support multiple Calcus instances as long as it
wasn't in a multi-threaded environment. Not easy but possible.
--
Andrue Cope [TeamB]
[Bicester, Uk]
http://www.yqcomputer.com/
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Wed, 01 Mar 2006 02:14:34

Well my english is a little poor to explain correctly my problem !
So i try to simplify the situation with my little program that produce the
problem. But maybe i symplify too much !

In the real problem, i have a library (dll) or a set of routine who provide
some methods to solve problem (the "somme" function in my sample) and the
associated header file.
In my class ("Calcul" in my simple), i want to call some methods of the
library. The problem is that some arguments of the method are functions of
my class.

Note : I have only one instance of my class and there are no thread.

Hope is more clear ;)

Thanks again,
Lionel



"Andrue Cope [TeamB]" < XXXX@XXXXX.COM > a rit dans le message
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Andrue Cop » Wed, 01 Mar 2006 02:24:42


In that case my second example is what you want. It's ugly and
personally I would want to add safeguards but it'll work fine.

--
Andrue Cope [TeamB]
[Bicester, Uk]
http://www.yqcomputer.com/
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Wed, 01 Mar 2006 02:41:48

Thanks Andrue,

Maybe i misunderstood your example, but you change the code of "somme" by
adding "void *this". I see why but i can not do that because in the real
problem i can not modify the code of the library ;(

I need a way with no change over the function "somme". I can encapsulate it
and do what i want around it but not change it !!
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Tom Widme » Wed, 01 Mar 2006 02:59:37


You need to read his post further - the second example actually includes
two examples.

Tom
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Wed, 01 Mar 2006 03:18:17

Hi Tom,

Yes i read the second part too. But the function "somme" is also altered.

I maybe found i solution :
I declare "static" the function "DoFacteur", so no problem to pass the
function to "somme". But now i can not access at "Facteur" in "DoFacteur",
so i create a global instance of my class named "GlobalInstance" and replace
"Facteur" by "GlobalInstance->Facteur".

I don't know if it's clean, but seems to work !!

Thanks everybody,
Lionel
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Andrue Cop » Wed, 01 Mar 2006 18:13:17


That's what my second example is doing.

--
Andrue Cope [TeamB]
[Bicester, Uk]
http://www.yqcomputer.com/
 
 
 

Can't convert 'double(*(_closure)(double))(double)' in 'double (*)(double)' error

Post by Lionel Rey » Wed, 01 Mar 2006 18:54:59

Hi Andrue

Yes that was the idea. We only undestand well that what we do alone !!

Thanks for your help,
Lionel