Timothy Ritchey wrote:
I have an interpreter that uses a visitor pattern while performing a reduction of the program tree. As part of the visitor pattern, each class that can be a node in the tree must respond to:
virtual void accept(Visitor& v);
where each node then implements by calling visitor with itself using the proper type. The function calls in visitor are like:
void visit(shared_ptr<Node> node); void visit(shared_ptr<Type> node); etc.
(where Type is a descendant of node BTW).
Interesting. Why do you need to pass a shared_ptr to the visitor?
Normally with the visitor pattern (GOF style in this case), the implementation of accept is simply:
void Node::accept(Visitor &v) { v.visit(this); }
I've tried adding enable_shared_from_this<...> as a superclass of my nodes, and returning shared_from_this(), which works in some cases, but in others just seems to hang. These occur in classes that are a little more complex. For example, I have a TypeTemplate<T> class that wraps to underlying types TypeTemplate<int>, TypeTemplate<float>, TypeTemplate<etc>. I've tried adding enable_shared_from_this
, and then having an implmentation void TypeTemplate<T>::accept(Visitor &v) { v.visit(enable_shared_from_this
::shared_from_this()); }
but it just hangs on both vc7.1 on windows and Xcode on OS X. (I had to add the extra scoping because I got complaints that "shared_from_this() was ambiguous in multiple inheritance.")
shared_from_this() shouldn't hang; can you simplify this down to a minimal example? Since shared_from_this() is ambiguous, I take it that your class has several enable_shared_from_this base classes. This doesn't work; at most one of them will be initialized properly, the rest will (should) just throw bad_weak_ptr. You'll need to try to eliminate the multiple enable_shared_from_this bases. This can typically be done by following the "non-leaf classes should be abstract" advice. IOW: class Node: public enable_shared_from_this<Node> {}; class Type: public Node, public enable_shared_from_this<Type> {}; needs to be refactored as: class AbstractNode { /* pure virtuals */ }; class AbstractType: public AbstractNode { /* pure virtuals */ }; class Node: public AbstractNode, public enable_shared_from_this<Node> {}; class Type: public AbstractType, public enable_shared_from_this<Type> {}; This is the best advice I can offer without more information. :-) I hope that it helps.