C ++ возвращает значение вызывающей стороне из глубокого стека без `throw` - PullRequest
0 голосов
/ 21 апреля 2020

Я использую шаблон посетителя для обхода дерева, состоящего из множества различных типов узлов, что-то вроде этого:

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 &)?

...