From: Hamish Mackenzie (hamish_at_[hidden])
Date: 2003-06-25 07:14:52
On Wed, 2003-06-25 at 01:12, Stefan Seefeld wrote:
> hi there,
> some weeks ago I proposed an API for XML, which triggered an interesting
> discussion. Hamish Mackenzie proposed a somewhat simpler mechanism to attach
> the C++ wrapper objects to the C structs from libxml2.
> I reworked the API to use that mechanism, so now using an xml document
> looks somewhat like:
> dom::document_ptr document("1.0");
> dom::element_ptr root = document.create_root_node("root");
> dom::element_ptr child = root.append_child("child");
> dom::text_ptr text = root.append_text("hello world");
> for (dom::element_ptr::child_iterator i = root.begin_children();
> i != root.end_children();
> std::cout << i->get_name() << std::endl;
> As the wrapper objects have reference semantics, I append '_ptr' to
> their name to stress that fact. A practical side-effect of this is
> that the document is now ref-counted, as it doesn't own the node-wrappers
> any more (as was the case in my former API).
Why should the node-wrappers keep the document alive?
Here is the analogy I think works best...
container --> document
container::value_type --> node
container::iterator --> node_iterator
container::pointer_type --> node_pointer
container::reference_type --> node_reference
Consider the following....
std::vector< foo > x;
foo * y = &x;
x.erase( x.begin(), x.end() );
I don't expect y to add_ref x. I wouldn't mind if it did, but it
wouldn't make y any more valid after the call to erase.
So the problem with add reffing the document is... what happens if the
root node or some parent of a node you have a pointer to is erased from
the document? libxml2 has no way of knowing you have a pointer to a
I think the solution is that the node iterators/pointers/reference
should not own anything (as is the convention with containers). The
document owns the root node, the root node owns it's children and so on.
If a particular implementation (such as MSXML) has ref counting built in
that's fine but it should not be a requirement. The boost::xml
interface requirements could simply state "iterators, pointers and
references for nodes are invalidated by deleting the document to which
they belong or by erasing them from the document (erasing a parent node
erases it's children)". It doesn't matter if for some implementations
they are still valid. We can add a remove function something like...
std::auto_ptr< document > remove( node_iterator i );
This would take a node and all its children and put them in a new
document object. An implementation that has a underlying mechanism for
nodes to exist without the implementations document object could allow
xml::document to exist with just a root node and make the appropriate
optimisation to remove.
-- Hamish Mackenzie <hamish_at_[hidden]>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk