Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old August 28th, 2008, 07:25 PM
Giovanni Gherdovich
Guest
 
Posts: n/a
Default returned type of boost::bind && Address of a tmp object

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
  #2  
Old August 28th, 2008, 07:45 PM
Eric.Malenfant@gmail.com
Guest
 
Posts: n/a
Default Re: returned type of boost::bind && Address of a tmp object

On Aug 28, 2:18*pm, Giovanni Gherdovich
<gherdov...@students.math.unifi.itwrote:
Quote:
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.
Quote:
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.../function.html

HTH,

Éric Malenfant
  #3  
Old August 28th, 2008, 07:55 PM
gpderetta
Guest
 
Posts: n/a
Default Re: returned type of boost::bind && Address of a tmp object

On Aug 28, 8:18*pm, Giovanni Gherdovich
<gherdov...@students.math.unifi.itwrote:
Quote:
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:
>
<snip>
Quote:
>
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?
>
<snip>
Quote:
struct oneVar_function *// one variable function
{
* double (* function) (double x, void* params);
* void* params;
>
};
<snip>
Quote:
>
* 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.

--
gpd

  #4  
Old August 28th, 2008, 11:35 PM
Giovanni Gherdovich
Guest
 
Posts: n/a
Default Re: returned type of boost::bind && Address of a tmp object

Hello,

thank you for your answers.

Eric:
Quote:
Have a look at boost::function
gpd:
Quote:
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
 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles