c++boostptr-vector

How to retrieve a reference from a boost ptr_vector?


I have two classes: an Object class, and an ObjectManager class. The ObjectManager class stores "Objects" via a ptr_vector container. There are some instances where I need to retrieve references to these stored pointers to perform individual actions on them. How would I go about doing so?

Compilable Pseudo Code:

#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/shared_ptr.hpp>

class Object
{
public:
  int m_Id;
  Object(int id) : m_Id(id) { }
};

class ObjectManager
{
private:
  typedef boost::shared_ptr<Object> ObjectPtr;
  typedef boost::ptr_vector<Object> ObjectVectorPtr;
  typedef ObjectVectorPtr::iterator ObjectIt;

  ObjectVectorPtr vector_;

  void AddObject(Object *obj) {
    vector_.push_back(obj);
  }

  ObjectPtr FindObject(int id) {
    for (ObjectIt it = vector_.begin(); it != vector_.end(); it++) {
      if (it->m_Id == id) {
        // Found the object...How to return a shared_ptr reference to it?
        // The line below is invalid, obviously:
        // cannot convert parameter 1 from 'Object' to 'const boost::shared_ptr<T> &'
        return *it;
      }
    }

    // We could not find anything.
    return ObjectPtr();
  }
};

Basically I want the ObjectManager to retain ownership, but I also want other classes to be able to get a reference to the object, use call methods on that object depending on what's going on, and move on.


Solution

  • Convert your container to use shared_ptr as the member:

    #include <boost/ptr_container/ptr_vector.hpp>
    #include <boost/shared_ptr.hpp>
    #include <vector>
    
    class Object
    {
    public:
      int m_Id;
      Object(int id) : m_Id(id) { }
    };
    
    class ObjectManager
    {
    private:
      typedef boost::shared_ptr<Object> ObjectPtr;
      typedef std::vector<ObjectPtr> ObjectVectorPtr;
      typedef ObjectVectorPtr::iterator ObjectIt;
    
      ObjectVectorPtr vector_;
    
      void AddObject(ObjectPtr& obj) {
        vector_.push_back(obj);
      }
    
      ObjectPtr FindObject(int id) {
        for (ObjectIt it = vector_.begin(); it != vector_.end(); ++it) {
          if (it->get()->m_Id == id) {
            // Found the object - return a shared_ptr reference to it
            return ObjectPtr(*it);
          }
        }
    
        // We could not find anything.
        return ObjectPtr();
      }
    };
    

    btw - prefer ++it vs it++ to avoid extra construction, and don't use matching like this if the container gets large - switch to std::map<int, ObjectPtr> with m_id as the key, or std::set with suitably-defined less function.

    If I was being super-pedantic I would suggest replacing your find loop with a call to std::find_if, with a predicate that matches on Object::m_id...