Boost logo

Boost :

Subject: Re: [boost] Weak functor: Interested? (How to boost::bind to a weak_ptr)
From: Vladimír Tøebický (vladimir.trebicky_at_[hidden])
Date: 2012-01-10 16:18:09


>> Hi!
>>
>> I saw people asking how to do boost::bind using a weak pointer.
>> Generally it's not possible without first specifying what should
>> happen if the weak_ptr cannot be converted to shared_ptr. The
>> "weak_fn" I wrote is a small class holding a member pointer, a weak
>> pointer and a "policy":
>>
>> * It is callable so you can insert it to boost::bind.
>> * You can construct it using free function templates.
>> * The policy says what should happen when the object is called yet the
>> weak_ptr cannot be converted to shared_ptr.
>> * It's implemented both using variadic templates and Boost.Preprocessor.
>>
>> Copy of the help comment:
>>
>> /** Returns a callback that can be used eg. in boost::bind. When called, it
>>  * tries to lock weak_ptr to get a shared_ptr. If successful, it calls
>>  * given member function with given arguments. If not successful, it calls given
>>  * policy functor. Built-in policies are:
>>  *
>>  * "ignore_if_invalid" - does nothing
>>  * "throw_if_invalid" - throws "bad_weak_ptr"
>>  * "return_default_if_invalid" - returns given value
>>  *
>>  * Example:
>>  *
>>  * struct Foo {
>>  *     void bar(int i) {
>>  *         std::cout << i << std::endl;
>>  *     }
>>  * };
>>  *
>>  * struct do_something {
>>  *     void operator()() {
>>  *         std::cout << "outdated reference" << std::endl;
>>  *     }
>>  * };
>>  *
>>  * int main()
>>  * {
>>  *     boost::shared_ptr<Foo> sp(new Foo());
>>  *     boost::weak_ptr<Foo> wp(sp);
>>  *
>>  *     boost::bind(boost::weak_fn(&Foo::bar, wp), _1)(1);
>>  *     sp.reset();
>>  *     boost::bind(boost::weak_fn(&Foo::bar, wp), 1)();
>>  *     boost::bind(boost::weak_fn(&Foo::bar, wp, do_something()), 1)();
>>  * }
>>  */
>>
>> What's missing:
>>
>> * Cannot point to a free function. Only member functions.
>> * ?
>>
>> Wdys?
>>
>> Vladimir.
>
> I beleive people want to use std::weak_ptr with std::bind when they
> want to store a callback, not just passing a functor to an algorithm,
> and when people do that, that usually means storingin in an
> std::function instance. We already have similar pattern for
> shared/weak pointers, so wouldn't it be better to adopt an existing
> desing and make weak_fn noncallable, but with the ability to obtain an
> std::function instance from it, that would store a strong reference to
> the object via shared_ptr?

I think there's a slight misunderstanding. The way it is designed
doesn't only allow you to pass it as a functor to an algorithm. Of
course you can do that. But you can also pass it to boost::bind and/or
from boost bind to boost::function as you propose:

boost::function<void(int)> f = boost::bind(boost::weak_fn(&Foo::bar,
some_weak_ptr), _1);
f(1);

(Plus all the other examples above.)

Similarly to boost::bind, boost::fn is a function that returns an
instance of weak_fn_storage whose operator() mimics the prototype of
the bound member function (ie. returns the same type and can be
invoked with identical arguments). You can then invoke it directly or
-- more typically -- pass it to boost::bind for which it appears as a
"callable" to which it can pass the bound arguments when invoked. The
result of boost::bind can then be converted to boost::function if you
like, of course.

Vladimir.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk