I am working with a codebase that implements a custom datastructure consisting of several different node
types, all of which provide an accept
method that allows using visitor
types for the implementation of operations such as printing, evaluating, reformulation, etc.
One of these operations is copying a node
(and if they happen to be nonterminal any children) implemented in a templated copyCreator
visitor
. An excerpt of it is given below:
template<typename copyNodeType> struct copyCreator : public baseVisitor {
copyCreator(scope * globalScope) : baseVisitor(globalScope) {}
copyCreator(
scope * globalScope,
node * firstVisit) :
baseVisitor(globalScope) {
firstVisit->accept(*this);
}
~copyCreator() {
copy.reset();
for(auto ptr : openList) {
delete ptr;
}
}
std::unique_ptr<copyNodeType> copy = 0;
vector<nonterminalNode *> openList;
bool error = true;
// push to tree
template<typename nodeType>
void push(nodeType * ptr) {
if (copy) {
openList.back()->add_child(ptr); // if root is set, append to tree
}
else {
//setCopy<nodeType>(ptr);
auto temp = dynamic_cast<copyNodeType *>(ptr);
if(temp) {
copy = std::unique_ptr<copyNodeType>(temp);
error = false;
}
else {
delete ptr;
}
}
}
//...
//Example nonterminal node
void visit(struct sinNode & nod) {
auto next = new sinNode;
push(next);
openList.push_back(next);
nod.child->accept(*this);
openList.pop_back();
};
My issue is that it may happen that we enter the push
method for the first time and fail to encuonter the correct node type (copyNodeType
). If this happens in a nonterminal node type such as the sinNode
above, this will cause a nullptr
to be pushed to the open list and the walk continues with an incorrect state.
The obvious solution is enclosing everything following the push(next)
call in an if(next) { \\... }
, but that is both cumbersome and doesn't seem like a very elegant solution. As the push
method is being called from within the visit
methods, I see no easy way to carry the information from a failed push
outside without some flag that would need to be implemented in all the visit
methods for every single nonterminal node
type.
Is there some construct that allows exiting the first visit or otherwise implement a cancellation of the walk that I am not aware of?
Aucun commentaire:
Enregistrer un commentaire