
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.