Reputation: 5265
I've been reading up on boost::function
and boost::bind
, however, I can't seem to figure out a "good way" to call a boost
function if all the arguments are bound (I think that's the right terminology). Below is an untested MCVE (copying-and-pasting my real code is not ideal).
#include "boost/function.hpp"
#include "boost/bind.hpp"
#include <iostream>
void func(void* args)
{
int* myInt = static_cast<int*>(args);
if (myInt != NULL)
{
std::cout << "myInt = " << *myInt << std::endl;
}
else
{
std::cout << "args is NULL" << std::endl;
}
}
int main()
{
int myInt1 = 5;
int myInt2 = 45;
boost::function<void(void* args)> myFunc = boost::bind(&func, &myInt1);
// here's my problem,, how do I call myFunc?
myFunc(); // this does not compile due to missing arguments
myFunc; // this is essentially a no-op. The function doesn't execute,
// and if I put a breakpoint here, it either goes to the next
// line or I get a warning that no executable code exists here
// after some experimentation, I realized I can do this and it works
myFunc(NULL); // this prints out "myInt = 5"
// this also prints out "myInt = 5"
boost::bind(&func, &myInt1)();
// finally, this prints out "myInt = 5" as well
myFunc(&myInt2);
return 0;
}
So my question is, what's the preferred/right way to call myFunc
? I've successfully called functions with the _1
, _2
, etc argument placeholders by passing in the appropriate arguments.. maybe in practice there are placeholders almost all the time? myFunc(NULL)
works, but it seems silly to me that I must essentially make up arguments if I've already bound them (and what I pass in doesn't matter anyway). In my real code, I actually want to call myFunc
in a different function (so boost::bind(&func, &myInt1)();
isn't an option), and I'm doing so inside an object of a class, so I hope the example I've provided exhibits identical behavior to what I'm seeing in my real code. I'm using Visual Studio 2013, and c++11 or later cannot be used.
Upvotes: 2
Views: 1096
Reputation: 72271
A better type for your myFunc
variable would be boost::function<void()>
, because with all arguments of the original func
bound, no arguments are really needed to call the resulting wrapper.
boost::function<void()> myFunc = boost::bind(&func, &myInt1);
This would in fact allow you to call the function with just:
myFunc();
But the reason the compiler allowed the boost::function<void(void*)>
type there is that the result of a boost::bind
call can be called with more arguments than necessary if you choose to, and extra arguments are just ignored. One thing this does is makes situations like this a bit more consistent:
void f(int, int);
// g1 acts the same as f:
boost::function<void(int, int)> g1 = boost::bind(f, _1, _2);
// g2 swaps the order of arguments when calling f:
boost::function<void(int, int)> g2 = boost::bind(f, _2, _1);
// g3 ignores its first argument and passes the second to f twice:
boost::function<void(int, int)> g3 = boost::bind(f, _2, _2);
// g4 ignores its second argument and passes the first to f twice:
boost::function<void(int, int)> g4 = boost::bind(f, _1, _1);
In the g4
initialization, we can say the bind
expression is just another bound function that can be called with exactly two int
arguments, because it doesn't use any placeholders with position larger than 2. It can also be called with just one argument since _2
itself isn't ever used either, but that doesn't make the above false.
So similarly, in your code initializing boost::function<void(void*)>
, the compiler accepts the completely bound bind
expression as something which can validly be called with one argument, since it doesn't use any placeholders with position larger than 1. Though since in fact it doesn't use the placeholder _1
with position exactly 1 either, the void*
input when used in that way just ends up being ignored.
Upvotes: 2
Reputation: 227390
A function object with "all parameters bound" has no parameters, so its type would be boost::function<void()>
. You need
boost::function<void()> myFunc = boost::bind(&func, &myInt1);
Upvotes: 5