Я использую шаблон посетителя для обхода дерева, состоящего из множества различных типов узлов, что-то вроде этого:
class Visitor
{
public:
virtual void visit(TypeA &) = 0;
virtual void visit(TypeB &) = 0;
virtual void visit(TypeC &) = 0;
virtual void visit(TypeD &) = 0;
virtual void visit(TypeE &) = 0;
virtual void visit(TypeF &) = 0;
virtual void visit(TypeG &) = 0;
virtual void visit(TypeH &) = 0;
virtual void visit(Returner &) = 0;
virtual void visit(Caller &) = 0;
};
Каждая из функций посетителя может потенциально вызывать любую другую функцию посетителя, поскольку типы расположены в дереве. Например, visit(TypeA &)
может быть реализовано следующим образом:
void ClassWhichInheritedVisitor::visit(TypeA & a){
a.bChild->accept(*this);
a.fChild->accept(*this);
a.callerChild->accept(*this);
}
Теперь у меня есть значение, сгенерированное в visit(Returner &)
, которое я хотел бы вернуть к самому последнему вызову visit(Caller &)
. Мое текущее решение - throw
значение из visit(Returner &)
и перехватить его в visit(Caller &)
, однако я прочитал, что обработка исключений может быть очень медленной.
Одним из решений может быть сохранение возвращаемого значения в некоторой переменной-члене и проверять значение после каждого вызова accept(*this)
для любого дочернего элемента, однако это делает код раздутым и трудным для чтения. Может быть, это можно облегчить с помощью макроса препроцессора?
#define visit(target); \
target->accept(*this); \
if (returnValuePresent) \
return;
Есть ли более идиоматический c способ вернуть это значение без проверки значения после каждого вызова accept(*this)
, учитывая, что может легко быть 5/6 функциональных вызовов между вызовами visit(Caller &)
и visit(Returner &)
?