Reputation: 21
I am using boost::bind to create composed functions on-the-fly, and hope to store the object as some class member variable for later usage. For example we have two functors:
struct add{double operator()(double x, double y) const{return x+y;};};
struct multiply{double operator()(double x, double y) const{return x*y;};};
Then to create a function f(x,y,z) = (x+y)*z, I can do this:
auto f = boost::bind<double>(multiply(), boost::bind<double>(add(), _1, _2), _3);
And calling f(x,y,z) works perfectly. Now I want to save f as a class member variable, something like the following:
struct F
{
auto func;
double operator(const std::vector<double>& args) const
{
return func(args[0],args[1],args[2]); //Skipping boundary check
}
}
F f_obj;
f_obj.func = f;
f_obj(args);
But of course I cannot declare an auto variable. Is there any way to get around this?
Note that I am not using boost::function, as it will dramatically impact the performance, which is important to me.
Thanks for any advice.
Upvotes: 2
Views: 685
Reputation: 154035
The type returned from bind()
is specific to each combination of function objects and arguments. If you want to store the result, you will need to erase the type in some way. The obvious approach is to use function<..>
.
When the resulting function object is invoked frequently, the overhead introduced by function<...>
effectively doing a virtual dispatch may be too high. One approach to counter the problem is to bundle the function object with suitable bulk operations and instead of storing the function object to store a suitable application. That won't help when individual calls are needed but when lots of calls are required the virtual dispatch is paid just once.
Upvotes: 3
Reputation: 18972
Two options: use boost::function
, and measure whether it actually affects performance.
Alternatively make F a template taking the type of func
as parameter and deduce it from the type of the bind
expression.
EDIT: The problem with the second option is it doesn't get rid of the awkward type. You can do that by defining a base class with a pure virtual function which the template overrides. But then you have dynamic memory to manage and the cost of a virtual function to pay - so you might as well go back to boost::function
(or std::function
) which does much the same thing for you.
Upvotes: 5