Boost logo

Boost :

From: Jeff King (peff-boost_at_[hidden])
Date: 2001-11-16 02:45:07


I'm considering a new poly_ptr class for boost; the intent is to aid in
the creation of heterogenous (polymorphic) containers.

Clearly, storing objects by value in standard containers will cause
slicing, so that's right out.

Storing raw pointers works, but is confusing and messy as far as
memory ownership. It also kills the "value" semantics of the containers;
copying an element actually copies an alias (which even further
complicates ownership).

Storing boost::shared_ptr<>s clears up the memory issue, but keeps the
aliasing problem. That is, users of the container must be aware that
pointers are being stored. Copying a range of elements with std::copy(),
for example, will not produce two copies of the elements, but rather two
points pointing to the same object. Sometimes this is desired, sometimes
not.

The idea of poly_ptr is to provide value semantics but to avoid slicing.
The general idea is this:

- heterogenous objects share a common base
- all objects are allocated via new
- a poly_ptr may be NULL, or may contain a pointer along with the
  pointer's type information
- copying a poly_ptr results in a non-sliced copy being allocated on the
  heap
- destroying a poly_ptr results in the object being deallocated via
  delete

Here's sample code to illustrate usage:

// declare 'derived1' and 'derived2', both inheriting from 'parent'
int main() {
  typedef poly_ptr<parent> phandle;
  typedef std::vector<phandle> pvector;

  pvector v;

  v.push_back(phandle::create(new derived1));
  v.push_back(phandle::create(new derived2));

  for(pvector::iterator i = v.begin(); i != v.end(); ++i)
    (*i)->some_virtual_function();

  return 0;
}

The syntax is a little funny (you must create either a NULL poly_ptr
with poly_ptr(), or you must use the static create() function); this is
because create() is a templated function that grabs the necessary type
info. You also still have to deal with the double dereference for the
iterator; I don't think it's possible to deal with this using standard
containers and not using a dereferencing iterator adaptor.

I have simple proof of concept code that gives the above code the
semantics you would expect. I can clean it up and post it if there is
sufficient interest. At this point, I just want to know:

- does this duplicate functionality already in boost?
- is there a better way to achieve the same ends?
- should this be part of boost?

-Peff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk