c++11 member function returns vector of raw pointers from vector of unique_ptr

For a start you can use ret.reserve(m_objs.size()) to pre-allocate the right number of elements.

Alternatively, don't return a vector for callers to iterate over directly, but expose a vector-like interface instead:

class MyClass {
  public:
    struct iterator;
    iterator begin();
    iterator end();
    MyObject* operator[](size_t n) { return m_objs[n].get(); }

  private:
    vector<unique_ptr<MyObject>> m_objs;
};

This allows the callers to modify the objects directly, rather than getting a container of pointers.


class MyClass {
  public:
   std::vector<std::unique_ptr<MyObject>> const& get_objs() const {
     return m_objs;
   }

  private:
    std::vector<std::unique_ptr<MyObject>> m_objs;
};

a const std::unique_ptr<MyObject>& cannot steal ownership, and is not the same as a std::unique_ptr<const MyObject>. A const std::vector<std::unique_ptr<MyObject>>& can only grant const access to its data.

In c++20 I would instead do this:

class MyClass {
  public:
   std::span<std::unique_ptr<MyObject> const> get_objs() const {
     return {m_objs.begin(), m_objs.end()};
   }

  private:
    std::vector<std::unique_ptr<MyObject>> m_objs;
};

which hides the implementation detail of "I am storing it in a vector" while exposing "I am storing it contiguously".

Prior to c++20, I advise finding or writing your own span type if you have the budget. They are quite useful.


If you can use Boost, try indirect_iterator (http://www.boost.org/doc/libs/1_55_0b1/libs/iterator/doc/indirect_iterator.html). You need to define iterator, begin and end in your class:

typedef boost::indirect_iterator<vector<unique_ptr<MyObject>::iterator> iterator;
iterator begin() { return make_indirect_iterator(m_objs.begin()); }

Then your class exposes iterator, the value of which is reference (not pointer!) to MyObject. You can iterate and access the elements of the vector directly.

Tags:

C++

C++11