1

I'm new with the Boost library, and I got a problam a bit complex for me. I tried to reformulate it with an example found in previous question that might fit well my problem. (The previous question is here)

#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

class Base
    : public boost::enable_shared_from_this<Base>,
      private boost::noncopyable
{
public:
        virtual void test() = 0;

protected:
        virtual void foo(int i) = 0;
};

class Derived
    : public Base
{
protected:
    void foo(int i)
    { std::cout << "Base: " << i << std::endl; }

    std::map<int, int> data;

public:     

    Derived()
    {
            data[0] = 5;
            data[1] = 6;
            data[2] = 7;
    }        

    void test()
    {
        std::for_each(data.begin(), data.end(),
            boost::bind(&Derived::foo, shared_from_this(),
                boost::bind(&std::map<int, int>::value_type::second, _1)));
    }
};

typedef boost::shared_ptr<Base> Base_ptr;

int main(int, const char**)
{

    std::set<Base_ptr> Bases_;
    Base_ptr derived(new Derived());

    Bases_.insert(derived);
    derived->test();


    return 0;
}

I have a base object which is contained in a set, and different derived objects (in this example, only one). The derived object should call his own protected method with a boost::bind. In the real problem, the boost::bind generate a callback method for an asynchronous operation, it's why (I think) I need a shared_ptr. Otherwise, using the pointer this instead of shared_from_this() resolve the problem.

When I compile this code, I got a long error message ended with (which I think is the most significant part):

bind_test.cpp:43:78:   instantiated from here
/usr/include/boost/bind/mem_fn_template.hpp:156:53: error: pointer to member type ‘void (Derived::)(int)’ incompatible with object type ‘Base’
/usr/include/boost/bind/mem_fn_template.hpp:156:53: error: return-statement with a value, in function returning 'void'

I tried to manage with more inheritance from enable_shared_from_this, and some static cast :

#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

class Base
    : public boost::enable_shared_from_this<Base>,
      private boost::noncopyable
{
public:
        virtual void test() = 0;

protected:
        virtual void foo(int i) = 0;
};

class Derived
    : public boost::enable_shared_from_this<Derived>,
      public Base
{
protected:
    void foo(int i)
    { std::cout << "Base: " << i << std::endl; }

    std::map<int, int> data;

public:     

    Derived()
    {
            data[0] = 5;
            data[1] = 6;
            data[2] = 7;
    }        

    void test()
    {
        std::for_each(data.begin(), data.end(),
            boost::bind(&Derived::foo, boost::enable_shared_from_this<Derived>::shared_from_this(),
                boost::bind(&std::map<int, int>::value_type::second, _1)));
    }
};

typedef boost::shared_ptr<Base> Base_ptr;

int main(int, const char**)
{

    std::set<Base_ptr> Bases_;
    Base_ptr derived(new Derived());

    Bases_.insert(derived);
    derived->test();


    return 0;
}

But I got an error at run-time :

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr> >'
  what():  tr1::bad_weak_ptr

Might someone have a clue about how to manage that ? Thanks.

Etienne.

Community
  • 1
  • 1
etnbrd
  • 471
  • 6
  • 18
  • The `bind` statement makes no sense on multiple counts. Most strikingly, you cannot easily get at the pair's second member like that. Can you rewrite the function signature of `foo()`? – Kerrek SB Sep 07 '11 at 21:52
  • 2
    Inheriting from enable_shared_from_this in base and derived can lead to problems. I would avoid that route. http://stackoverflow.com/questions/657155/how-to-enable-shared-from-this-of-both-parend-and-derived – Tom Kerr Sep 07 '11 at 22:11
  • @Kerrek SB, in fact, this example is really more simple than the real problem. Actually I use boost::bind to generate a callback function for asynchronous operation on a socket called socket_ : void derived::test() { socket_.async_read_some(boost::asio::buffer(buffer_), boost::bind(&Derived::foo, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } foo is my callback, and is actually called handle_read, or handle_write. – etnbrd Sep 07 '11 at 22:34
  • @Tom K, I was confronted to problems due to this double inheritance. It's why I need to specify : boost::enable_shared_from_this::shared_from_this() Instead of : shared_from_this() – etnbrd Sep 07 '11 at 22:36
  • @Etienne: Be that as it may, that still doesn't save you from having to deal with the map's value being `pair`. You either write a little projector function or make the recipient accept the pair... – Kerrek SB Sep 07 '11 at 22:37
  • @Kerek SB, In my real code, there is no map. The map come from the example I used to illustrate my problem. If you want to see the actual, and complex problem, give a look [here](https://github.com/gravitezero/Node/blob/experimental/src/input_connection.cpp) – etnbrd Sep 07 '11 at 22:42

1 Answers1

1

It works with this workaround, but I'm not satisfied with it, so if someone find a better solution, go ahead.

#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

class Base
    : public boost::enable_shared_from_this<Base>,
      private boost::noncopyable
{
public:
        virtual void test() = 0;

//protected:
        virtual void foo(int i) = 0;
};

class Derived
    : public Base
{
protected:
    void foo(int i)
    { std::cout << "Base: " << i << std::endl; }

    std::map<int, int> data;

public:     

    Derived()
    {
            data[0] = 5;
            data[1] = 6;
            data[2] = 7;
    }        

    void test()
    {
        std::for_each(data.begin(), data.end(),
            boost::bind(&Base::foo, shared_from_this(),
                boost::bind(&std::map<int, int>::value_type::second, _1)));
    }
};

typedef boost::shared_ptr<Base> Base_ptr;

int main(int, const char**)
{

    std::set<Base_ptr> Bases_;
    Base_ptr derived(new Derived());

    Bases_.insert(derived);
    derived->test();


    return 0;
}
etnbrd
  • 471
  • 6
  • 18