Boost logo

Boost Users :

Subject: Re: [Boost-users] "weak" binding to member?
From: Igor R (boost.lists_at_[hidden])
Date: 2011-09-13 05:35:37


> 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)

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);
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net