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.