$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-06-13 10:17:37
On Wednesday 13 June 2001 10:29, you wrote:
> williamkempf_at_[hidden] writes:
> | > So the boost::function<> or the object returned from bind need to be
> | > packaged somehow to be able to pass it through a queue.
> |
> | Bind should not do this, as it's an orthogonal concept, as pointed
> | out.
>
> no I want the defer_call to do that...
>
> | > So perhaps a "defer_call" that packages function objects with
> | > operator()() would be more suitable for Boost.Thread or boost in
> | > general?
> |
> | Boost.Function already does this (I assume you're confused about this
> | because there are no virtual methods in boost::function<>, but trust
> | us, Boost.Function is a "deferred call" model).
>
> I might be confused... but I really cannot see how I can pass a
> function<> through a queue. (without limiting to only one return type)
>
> OR... all such object need to f.ex. be repackaged into function<void>
> before being passed to the queue. (it that even allowed?)
Perhaps some examples would help. Here's some of what Boost.Function can do:
static void printNum(int i) { cout << i << endl; }
struct PrintAndNegate {
int operator()(long i) const { cout << -i << endl; return -i; }
};
--- boost::function<void, int> f; f = printNum; // ... f(5); // prints 5 because "f" contains a pointer to printNum // ... f = PrintAndNegate(); // ... f(6); // prints -6 because "f" contains a printAndNegate object --- The assignments to f are done far in advance of the calls to "f", so boost::function is deferring calls. "f" is declared to take a single int parameter and return void. printNum exactly matches this signature, so we would expect it to work. PrintAndNegate, however, requires a conversion from int->long and requires "f" to swallow the int return value (it does both, so the above code works). The above code is a deferred call. Now take a step over to the realm of binding arguments. I'll just do something the standard library has: void multiply_and_print(int x, int y) { cout << x*y << endl; } // ... vector<int> v; // put some numbers in v... for_each(v.begin(), v.end(), bind1st(&multiply_and_print, 42)); So this code prints each of the numbers in v multiplied by 42. The bind1st function takes a function object (or function pointer) and an argument (42 in our case) and returns a new function object that calls the function pointer (to multiply_and_print) with the first parameter bound to 42. Now, we can use these two concepts together to get what you originally wanted from defer_call. However, note that the two concepts have no overlap. Neither example requires any part of the other. So now we can use a bound multiply_and_print with boost::function f = bind1st(&multiply_and_print, 42); // ... f(3); // prints 126 For your example with the queue of threads to start, you would have to decide on a common return type for the boost::function objects (most likely void). The return type of the actual functions that are being called as threads won't be relevant, then, because the result will be eaten by boost::function. This is no less powerful than your defer_call example: the return types must all be normalized to one type anyway because of static type checking. Doug