returned type of boost::bind && Address of a tmp object

  • Thread starter Giovanni Gherdovich
  • Start date
G

Giovanni Gherdovich

Hello,

in the following code I have a pointer (to function), say p,
of type
double (*)(double, double, void*)
and I try to fix the second argument of the function *p
to a given value (using boost::bind), but the compiler
complains, because of a type mismatch in an assignment
which I think should be legal:

/*
* bash-3.00$ g++ function.cpp
* function.cpp: In function `int main()':
* function.cpp:36: warning: taking address of temporary
* function.cpp:36: error: cannot convert
* `boost::_bi::bind_t<double,
* double (*)(double, double, void*),
* boost::_bi::list3<boost::arg<1>,
*
boost::_bi::value<double>,
* boost::arg<2> > >*'
* to `double (*)(double, void*)' in assignment
*/

Can you see why? The code is below.

There is also a warning which I don't like at all,
and remebers me that boost::bind( ... ) is a temporary
object and its address makes sense only in the current
scope (if I'm not wrong).
Since I have to pass this address as argument to another
function (later, in my real code), this can couse problems.

How can I build a "real" (I mean non-temporary) object
out of boost::bind( ... ), so that its address can
be passed forth and back across my code?

Regards,
Giovanni


// ---------------------------------------------- the file
function.cpp
#include <boost/bind.hpp>

struct oneVar_function // one variable function
{
double (* function) (double x, void* params);
void* params;
};

struct twoVar_function // two variables function
{
double (* function) (double x, double y, void* params);
void* params;
};

double
my_function (double x, double y, void* params)
{
// I cast `params` to double*.
// The user will be kind enough to always
// give a double* as 3rd argument when
// calling my_function.
double* alpha = static_cast<double*>(params);
return x + y + *alpha; // or whatever
}

int main()
{
twoVar_function f;
oneVar_function g;

f.function = &my_function;
double alpha = 3;
f.params = &alpha;

double a_given_number = 2;
g.function = &(boost::bind(*(f.function),
_1,
a_given_number,
_2));
g.params = &alpha;
}
// -------------------------------------- end of the file function.cpp
 
E

Eric.Malenfant

Hello,

in the following code I have a pointer (to function), say p,
of type
double (*)(double, double, void*)
and I try to fix the second argument of the function *p
to a given value (using boost::bind), but the compiler
complains, because of a type mismatch in an assignment
which I think should be legal:

/*
 *  bash-3.00$ g++ function.cpp
 *  function.cpp: In function `int main()':
 *  function.cpp:36: warning: taking address of temporary
 *  function.cpp:36: error: cannot convert
 *         `boost::_bi::bind_t<double,
 *                             double (*)(double, double, void*),
 *                             boost::_bi::list3<boost::arg<1>,
 *
boost::_bi::value<double>,
 *                                               boost::arg<2> > >*'
 *           to `double (*)(double, void*)' in assignment
 */

The compiler message says that the result of boost::bind is not
convertible to a function pointer.
boost::bind is a function template which returns an object (the type
of this object is a function of the parameters passed to the
boost::bind invocation), not an "ordinary" function.

The warning about taking the address of a temporary is because your
code takes the address of that object returned by boost::bind.
How can I build a "real" (I mean non-temporary) object
out of boost::bind( ... ), so that its address can
be passed forth and back across my code?

Have a look at boost::function: http://www.boost.org/doc/libs/1_36_0/doc/html/function.html

HTH,

Éric Malenfant
 
G

gpderetta

Hello,

in the following code I have a pointer (to function), say p,
of type
double (*)(double, double, void*)
and I try to fix the second argument of the function *p
to a given value (using boost::bind), but the compiler
complains, because of a type mismatch in an assignment
which I think should be legal:

Can you see why? The code is below.

There is also a warning which I don't like at all,
and remebers me that boost::bind( ... ) is a temporary
object and its address makes sense only in the current
scope (if I'm not wrong).
Since I have to pass this address as argument to another
function (later, in my real code), this can couse problems.

How can I build a "real" (I mean non-temporary) object
out of boost::bind( ... ), so that its address can
be passed forth and back across my code?

struct oneVar_function  // one variable function
{
  double (* function) (double x, void* params);
  void* params;

};

  double a_given_number = 2;
  g.function = &(boost::bind(*(f.function),
                             _1,
                             a_given_number,
                             _2));

'Bind' does not return a function pointer but an unspecified function
object (sort of a closure).

Thus there are two problems: first the assignment is illegal: you are
trying to convert a pointer to such a function object to a pointer to
a function. Second, as the compiler warns you, grabbing the address of
the temporary object returned by bind is a dangerous action, because
the temporary will be destroyed at the end of the expression.

As the exact result type of 'bind' is unspecified (well, you can see
it in the error message, but you shouldn't rely on it), you will have
to use boost::function as the type of the 'function' member of
oneVar_function:

#include <boost/function.hpp>
struct oneVar_function // one variable function
{
boost::function<double (double x, void* params)> function;
void* params;
};

[note: unteste code]
Note that boost::function can store function pointers as well as
function objects.
 
G

Giovanni Gherdovich

Hello,

thank you for your answers.

Eric:
Have a look at boost::function
gpd:
As the exact result type of 'bind' is unspecified (well, you can see
it in the error message, but you shouldn't rely on it), you will have
to use boost::function as the type of the 'function' member of
oneVar_function: [...]

I implemented my (wanna-be) callbacks as boost::function instead of
function pointers, and the two problems I mentioned in my previous
post are gone.

Furthermore I feel that switching the whole design of my real code
to boost::function will be straightforward. Cool!

Here is the modified version of my toy example, which compiles
and works fine:

// ---------------- this is the file function2.cpp
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

struct oneVar_function // one variable function
{
boost::function<double (double x, void* params)> function;
void* params;
};

struct twoVar_function // two variables function
{
boost::function<double (double x, double y, void* params)> function;
void* params;
};

double
my_function (double x, double y, void* params)
{
// I cast `params` to double*.
// The user will be kind enough to always
// give a double* as 3rd argument when
// calling my_function.
double* alpha = static_cast<double*>(params);
return x + y + *alpha; // or whatever
}

int main()
{
double alpha = 3;
twoVar_function f;
oneVar_function g;

f.function = &my_function;
f.params = &alpha;

double a_given_number = 2;
g.function = boost::bind(f.function,
_1,
a_given_number,
_2);
g.params = &alpha;

std::cout << (f.function)(1, 2, f.params) << std::endl;
// expected: 6
std::cout << (g.function)(1, g.params) << std::endl;
// expected: 6

/*
* bash-3.00$ g++ function2.cpp
* bash-3.00$ ./a.out
* 6
* 6
* bash-3.00$
*/
}
// ---------------- end of file function2.cpp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top