Compile-Time Checking for Insertion Rights on a C++ DOM Tree
While working on a DOM data structure, I noticed that only detached
nodes and newly created nodes could be legally inserted into the
tree. Having read a little about smart pointers and design-by-
contract, I tried to enforce this condition by writing something
analogous to:
class Node {
private:
Node (std::string tag); // Clients: use Node::create() instead!
...
public:
static std::unique_ptr<Node> create(std::string tag);
std::unique_ptr<Node> detach();
void insertNodeAsFirstChild(std::unique_ptr<Node> child);
...
public:
bool isSpan() const;
...
private:
friend class std::unique_ptr<Node>;
virtual ~Node(); // all deletions should be done by unique_ptr
wrapper
};
There were some concrete advantages:
* The compiler protects against clients of the DOM inserting a node
into the tree which already had a parent (rather than only catching
such errors at runtime, as most other DOMs do)
* There is no need for garbage collection, since responsibility for
freeing removed nodes is managed by ownership transfer using the smart
pointer
But I'm not happy about the "unique_ptr" semantics. Clients of the
tree are still holding aliased pointers all over the place, so
patterns like this are everywhere:
std::unique_ptr<Node> newNode (Node::create("span"));
Node* nodePtr = newNode.get();
parentNode.insertNodeAsFirstChild(newNode);
if (nodePtr->isSpan()) {
...
}
What is being transferred around uniquely is the "right to insert this
node into a tree, and responsibility to destroy if you don't". I can
use a typedef to delegate "unique" to being an implementation detail.
But I'm still concerned about basing the implementation on a pointer
whose expectation is "uniqueness", even if it' seems to work the way I
want.
Are there more legitimate techniques that still give the benefits I'm
looking for? The project already links against boost, and is using C+
+0x. So if there's a better pattern which builds on that foundation,
I'd be happy to follow it. (Note: for unrelated technical reasons,
it's not a problem if these Node objects cannot be stack-allocated.)
Any pointers appreciated...no pun intended!! :)
Best,
Brian
---
http://hostilefork.com
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]