In C++11, I tend to have master objects that maintain sole ownership of a collection of some children objects. Let's assume these children objects are non-copyable (for instance, boost::noncopyable
).
Other code needs to access these children objects to do some temporary processing, but not keep references, or share ownership over these objects.
As such, my master objects tend to have some sort of a get_child()
method.
As an example, let's say I have a Master
object like this:
class Master {
private:
std::vector<std::unique_ptr<Child>> children;
...
public:
??? get_child(int index);
};
When writing the get_child()
method, I have 2 obvious options:
Return by pointer:
Child* get_child(int_index) { return children[index].get(); }
Return by reference:
Child& get_child(int index) { return *(children[index]); }
I thought I didn't like either of these (for reasons I explain below), so I came up with the following:
borrowed_ptr<Child> get_child(int index) {
return make_borrowed<Child>(children[index].get());
}
where borrowed_ptr
is a trivial class wrapping a pointer with no smarts. I provide its implementation at the end of this question.
To me, borrowed_ptr
indicates that there exists a unique_ptr
someplace, and this borrowed_ptr
should be used for a short time, and not be recorded for any circumstance.
I don't like returning by raw pointer (1.) because I feel that Child*
doesn't imply that there exists a unique_ptr<Child>
someplace. Namely, I already have a lot of raw pointers floating around (think handles received from libraries, or my code which is not using smart pointers). I feel borrowed_ptr
gives a little more information over a raw pointer.
I don't like returning by reference (2.) because of an additional reason. I am worried that I will write
Child child = get_child();
and invoke a copy when I didn't intend to.
My question: Is borrowed_ptr
silly? Does it raise red flags with experienced C++ developers? Is it a faux pas? Does it feel like a code smell? Do you feel I should rather do 1., 2. or something else altogether?
Here is my implementation of borrowed_ptr
:
template<typename T>
class borrowed_ptr {
private:
T* ptr;
public:
borrowed_ptr(const unique_ptr<T>& r) {
ptr = r.get();
}
inline T* operator->() {
return ptr;
}
inline const T* operator->() const {
return ptr;
}
inline T& operator*() {
return *ptr;
}
inline const T& operator*() const {
return *ptr;
}
};
boost::noncopyable
or have private copy constructors defined you will get compile error when attempting to copy the object so it is safe to return by ref. \$\endgroup\$std::shared_ptr
instead ofstd::unique_ptr
. Then you could usestd::weak_ptr
s. \$\endgroup\$