shared_ptr and shared_from_this
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).
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
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.
Peter, On Oct 22, 2004, at 11:03 AM, Peter Dimov wrote:
Why do you need to pass a shared_ptr to the visitor?
That is a very good question. I had a couple of motivations: first, I thought I read somewhere that it was generally a good idea to make interfaces take shared_ptrs in order to help with issues of ownership. Also, the visitor is being used to interpret a program tree, which involves a mixture of singleton functors as well as normal program constructs that are free to be destroyed once they are done. By taking shared_ptrs, it greatly simplifies the management of nodes when performing a reduction on the tree. That being said, I suppose I could have taken the pointers, and then just had local shared_ptrs in each function.
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:
Thanks for the advice. I was able to get it working once I made all non-leaf nodes abstract, and did a little refactoring of the tree. Thanks again for the help. Cheers, tim
participants (2)
-
Peter Dimov
-
Timothy Ritchey