I'm trying to do strange things again.
Okay, here's the general idea. I want a std::list
(and vector
and so on) that actually own the objects they contain. I want to move the values into it, and access them by reference.
Example using a list of unique_ptr:
using namespace std;
list<unique_ptr<T>> items; // T is whatever type
items.push_back(make_unique(...));
items.push_back(make_unique(...));
for ( unique_ptr<T> item : items )
item.dosomething();
With me so far? Good. Now, let's do it with stack semantics and rvalue references. We can't just use a list<T&&>
for obvious reasons, so we'd have to make a new class:
using namespace std;
owninglist<T> items;
items.push_back(T());
items.push_back(T());
for ( T& item : items )
item.dosomething();
Of course, I might want an owningstack
or owningvector
as well, so ideally we want it to be templated:
owning<std::list<T>> items;
The owning<U<T>>
class should inherit whatever push_back()
and pop_front()
etc functions the underlying collection has. Presumably to achieve that, I'd need to code a generic base class, and derive explicit specialisations for the collections that have unusual functions:
template<typename T> owning<std::queue<T>> : owningbase<T> {
void push_front() { ... }
}
I'm getting stuck on the iterators. The begin()
and end()
functions should return an iterator that works the same as the underlying collection's iterator would, except with an operator*()
that returns the item by lvalue reference instead of by value.
We'd need some way to transfer ownership of an item out of the list again. Perhaps the iterator could have an operator~
that returns the item as an rvalue, deletes the item from the list, and invalidates the iterator?
Of course, all this is assuming the underlying std::list
(or whatever) can be convinced to take an rvalue. If push_back()
copies the value in as an lvalue, then none of this is going to work. Would I be better off coding a container from scratch? If I did, is there some way to put the majority of the code for list
, queue
, stack
and vector
into a single base class, to save rewriting pretty much the same class four times over?
Perhaps I could introduce an intermediate class, some kind of wrapper? So owned<list<T>>
could inherit from list<refwrapper<T>>
or something? I know boost has a reference_wrapper
, but I'm not sure it fits this scenario.