Wednesday, June 17, 2009

Understanding boost::ptr_container

Pointer containers are exception-safe container of pointers. Using them can be slightly frustrating for the users of the standard library containers, because the interface of ptr_containers are slightly different from that of standard library containers.

For example, you would probably expect from a vector of pointers to return a pointer when you perform indirection:

std::vector v;
int* p = v[i]; // ok

But ptr_vector returns a reference:

std::vector v;
int* p = v[i] ; // error: does not compile
int& p = v[i]; // ok

But the interface of ptr_vector is suited to work with algorithms:

find(v.begin(), v.end(), 3); // works only with ptr_vector

Transform Iterators

The transform_iterator can used with maps to traverse over just the keys or just the values contained in the map. An adaptor can be written to convert a usual iterator of a map into an iterator that traverses only over the value. This adaptor would have to be rewritten for ptr_map and its relatives because of its different interface.

Erasing An Element Using auto_type

typedef boost::ptr_set S;
S s;
int* j = new int(3);
s.insert(j);
s.insert(new int(5));
s.insert(new int(7));
S::iterator it = s.find(3);
s.release(it);
std::cout << *j << std::endl; // produces 0xfeeefeee using VS

If the second last line is changed to

S::auto_type r =s.release(it);

the correct value 3 is printed. r acts just like auto_ptr: it holds a reference to the object and thus prevents it from destruction. The user has the responsibility to destroy r when the object is no longer needed. r can also be dereferenced:

std::cout << *r << std::endl; // prints 3

and the pointer can be released using r.release().

Known Issues

Currently, you also cannot store a pointer to a const inside the ptr_container.

Comparison with std container of pointers

TODO

Comparison with std container of shared pointers

TODO

Conclusion

The different interface of ptr_containers can be frustrating for new users but hopefully not so much after reading this article. The newer interface makes clear that the ptr_container has exclusive ownership and thus reduces bugs when compared to using a standard container of pointers.

No comments: