tom_usenet said:
It's possible, but I don't know of a free reference counted vector
implementation that conforms to the std::vector interface - it would
be easy to write one of course (though time consuming to code and
debug).
On the face of things I think it should be ok if I write my own. Maybe not a
full-blown version but at least something useful for my current project.
Here is something that I wrote based on the public interface of std::vector.
template <class T> class SharedVector
{
SharedPtr<std::vector<T> > ptr;
public:
typedef std::vector<T>::size_type size_type;
typedef IteratorNotDefinedYet iterator;
typedef ConstIteratorNotDefinedYet const_iterator;
explicit SharedVector() : ptr(new std::vector<T>) { }
explicit SharedVector(size_type n, const T &v = T()) :
ptr(new std::vector<T>(n,v)) { }
SharedVector(const SharedVector &x) : ptr(x.ptr) { }
SharedVector(const_iterator first, const_iterator last) :
ptr(new std::vector<T>(first, last)) { }
iterator begin() { return iterator(ptr->begin()); }
const_iterator begin() const { return const_iterator(ptr->begin(),
ptr); }
iterator end() { return iterator(ptr->end()); }
const_iterator end() const { return const_iterator(ptr->end(), ptr); }
T &operator[](size_type pos)
{
ptr.make_unique(); // "copy-on-write" before calling non-const
method
return ptr->operator[](pos);
}
const T &operator[](size_type pos) const { return
ptr->operator[](pos); }
};
I haven't thought alot about allocators, iterators or anything. Just the
obvious things. Feel free to point out what is wrong in the above design.
Note that in the posted code it would be a pessimization to have
reference counting. In the few cases where you do need it (to share
ownership of a vector), using a shared_ptr seems the obvious solution.
Why make a special case for a shared vector? int isn't shared...
Tom
C++ FAQ:
http://www.parashift.com/c++-faq-lite/
C FAQ:
http://www.eskimo.com/~scs/C-faq/top.html
Perhaps "SharedVector" isn't the right term. I thought of referring to it as
"VectorRef" instead but I changed my mind. Anyway I certainly believe that a
SharedVector would be much more convenient than a SharedPtr alone. Let me
write another example to make this clear.
class Book
{
std::string title;
SharedVector<Page> pages;
public:
Book(std::string title_, SharedVector<Page> pages_) :
title(title_), pages(pages_) { }
void find(std::string line, SharedVector<Page> &pages_) const {
for (int i=0; i < pages.size(); i++) {
if (pages
.contains(line))
pages_.push_back(pages);
}
}
friend std::istream &operator>>(std::istream &, Book &);
};
class Page
{
int number;
SharedVector<std::string> lines;
public:
bool contains(std::string line) const
{ return find(lines.begin(), lines.end(), line) != lines.end(); }
friend std:stream &operator<<(std:stream &, const Page &);
friend std::istream &operator>>(std::istream &, Page &);
};
using namespace std;
int main()
{
// read book from cin
Book book;
if (!(cin >> book))
return 1;
// find pages that contain the line "foo"
SharedVector<Page> pages;
book.find("foo", pages);
// make another book with them and call it "the story of foo"
Book another_book("the story of foo", pages);
// display the pages using const_iterators, so they stay shared
const SharedVector<Page> &const_pages = pages;
copy(const_pages.begin(), const_pages.end(),
ostream_iterator<Page>(cout, "\n"));
return 0;
};