提问人:Jacob 提问时间:7/12/2023 最后编辑:marc_sJacob 更新时间:7/30/2023 访问量:115
带有用于遍历树结构的模板的访客模式
Visitor Pattern with templates for traversing tree structure
问:
我得到了一个类似“树”的结构,它表示一个简单的加法表达式。(例 2 + 4 + (3 + 5))
我正在使用访客模式遍历树并找到总和。问题是我希望我的实现使用模板,这会导致一些奇怪的错误。
我需要每个子表达式的 accept 函数能够返回任何类型,以便我可以执行的不仅仅是整数运算
#include <iostream>
#include <vector>
#define print(x) std::cout << x << "\n";
class Add;
class Number;
// Basic template for visitor class
template <class T>
class Visitor {
public:
virtual T visitAdd(Add* add) = 0;
virtual T visitNumber(Number* num) = 0;
};
// Visitor made for adding
template <class T>
class Adder : public Visitor<T> {
public:
T visitAdd(Add* add) override;
T visitNumber(Number* num) override;
};
// Node types for expression tree
class Expr {
public:
template <class T>
virtual T accept(Visitor<T>* visitor) = 0;
};
class Add : public Expr {
public:
Expr* left;
Expr* right;
Add(Expr* left, Expr* right) : left(left), right(right) {};
template <class T>
T accept(Visitor<T>* visitor) {
return visitor->visitAdd(this);
}
};
class Number : public Expr {
public:
int value;
Number(int value) : value(value) {};
template <class T>
T accept(Visitor<T>* visitor) {
return visitor->visitNumber(this);
}
};
template <class T>
T Adder<T>::visitAdd(Add* add) {
return add->left->accept(this) + add->right->accept(this);
}
template <class T>
T Adder<T>::visitNumber(Number* num) {
return num->value;
}
int main() {
// Should represent (5 + 2) + (7 + (4 + 2))
Expr* expression = new Add(
new Add(
new Number(5),
new Number(2)
),
new Add(
new Number(7),
new Add(
new Number(4),
new Number(2)
)
)
);
// Print sum as int
Adder<int> intAdder = Adder<int>();
print(expression->accept(&intAdder));
// Print sum as float
Adder<float> floatAdder = Adder<float>();
print(expression->accept(&floatAdder));
return 0;
}
错误:函数模板声明中不允许使用“virtual” (对于 Expr::accept)
答:
0赞
jpalecek
7/30/2023
#1
解决此问题的一种方法是删除返回值并将结果保留在访问者中。这样就变成了Visitor<T>
struct Visitor {
virtual void visitAdd(Add* add) = 0;
};
Adder
也将删除返回值,并添加结果字段
template <class T>
struct Adder : public Visitor<T> {
void visitAdd(Add* add) override {
add->left->accept(this);
add->right->accept(this); }
... left as an exercise for the reader ...
并且还将删除其模板参数。然后,您必须从实例中提取结果。Expr::accept
main
Adder<int>
评论