"weak" binding to member?

I know that 'bind' (now in std::tr1) will bind pointers to member functions to smart pointers. But is there a simple way to bind to a "weak" pointer, such that the attempted call will realize the smart pointer and if successful perform the call, or if unsuccessful just not call anything without complaint? (In this case, it appears that the return is void) —John

I don't know what you mean by that.
I mean that you can pass a weak_ptr along with the binder: void setYourFunctor(const function<void(void)> &func, const weak_ptr<void> &track) { // store "func" and "track" func_ = func; track_ = track; } // Now in the place where "func_" should be called: void call() { shared_ptr<void> p = track_.lock(); if (p) func_(); } // Now use it this way: shared_ptr<YourClass> ptr = ...; setYourFunctor(bind(&YourClass::doSomething, ptr.get()), ptr);

Well, I think I've figured out how to solve your problem. Since Boost.Bind invokes your functor through ->* operator, you just need to define your own get_pointer() function that returns an adapter that defines ->* operator, which would do what you want. The last step is somewhat cumbersome, but you can use the following Meyers' article: http://www.aristeia.com/Papers/DDJ_Oct_1999.pdf I've tested the following code and it seems to work: #include <boost/bind.hpp> #include <boost/smart_ptr.hpp> #include <utility> template <typename C, typename R, typename F> class invoker { public: typedef std::pair<C*, F> call_info; invoker(const call_info& info) : ci_(info) {} R operator()() const { return ci_.first ? (ci_.first->*ci_.second)() : R(); } template <typename Arg1> R operator()(Arg1 p1) const { return ci_.first ? (ci_.first->*ci_.second)(p1) : R(); } template <typename Arg1, typename Arg2> R operator()(Arg1 p1, Arg2 p2) const { return ci_.first ? (ci_.first->*ci_.second)(p1, p2) : R(); } private: call_info ci_; }; template <typename T> class ptr_adapter { public: ptr_adapter(T *p): p_(p) {} template <typename R> const invoker<T, R, R (T::*)()> operator->*(R (T::*pmf)()) const { return std::make_pair(p_, pmf); } template <typename R, typename Arg1> const invoker<T, R, R (T::*)(Arg1)> operator->*(R (T::*pmf)(Arg1)) const { return std::make_pair(p_, pmf); } template <typename R, typename Arg1, typename Arg2> const invoker<T, R, R (T::*)(Arg1, Arg2)> operator->*(R(T::*pmf)(Arg1, Arg2)) const { return std::make_pair(p_, pmf); } private: T *p_; }; namespace boost { template<class T> ptr_adapter<T> get_pointer(const boost::weak_ptr<T> &p) { return ptr_adapter<T>(p.lock().get()); } } struct test { int func(int i, int j) { return i + j; } }; int main() { boost::shared_ptr<test> p(new test); boost::weak_ptr<test> w = p; auto func = boost::bind(&test::func, w, _1, _2); int res = func(1, 2); p.reset(); res = func(1, 2); }

On 9/13/2011 4:35 AM, Igor R wrote:
Interesting. I had thought about defining an adaptor that provided operator->, but that would not work with the semantics I want to duplicate. It would be perfect if you intended to throw an exception if the weak ptr was dead. But using ->* gives control over the actual call, so the code can be skipped. I suppose that the inner workings of bind must use operator->* at some point (how else can it work?) this would be portable, even though it's not mentioned in the documentation or the standard. I already wrote an adaptor that is analogous to mem_fn, which is probably about the same complexity as what you show, and doesn't court portability issues. But thank you very much for the idea; I think it is easy to forget about operator->* when looking for solutions. —John
participants (2)
-
Igor R
-
John M. Dlugosz