本文(http://accu.org/index.php/articles/2021)介绍了如何使用内联访问者的一个非常有趣的概念。我喜欢这种方法并试一试。但是,我遇到了一些问题。
不幸的是,实施起来很难深入理解。
示例:
// define the graph
struct Node {...};
struct Expr : Node {...};
struct Stat : Node {
Expr& sub_node; // introduce a subnode
// ...
}
// now the traversal with the inline visitor
auto v = begin_visitor<NodeVisitor>
.on<Expr>([&](Expr& e)
{
// do something with e
})
.on<Stat>([&](Stat& s)
{
// do something with s
// and then visit the sub_node of type 'Expr':
s.sub_node.accept(*this); // "usual visitor" way: obviously wrong
s.sub_node.accept(v); // cannot use variable in its initialization...
???
})
.end_visitor();
p.accept(v);
我很欣赏这种技巧的每一条评论或暗示。
谢谢&amp;问候
答案 0 :(得分:1)
网站上没有任何许可证。这个源代码可以免费使用吗?
没有。但是你可以向作者索取许可证,你当然可以使用他们的实现作为灵感来实现你自己的“内联访问者”。
图中的某些节点包含对子节点的引用。如果我的访问者遍历这样的节点,我想指定必须遍历子节点的顺序。
给定的代码不进行子节点遍历 - 它没有子模式的概念。您必须在相关的.on处理程序中执行此操作,与正常实现的访问者相同。我想象这样的事情(未经测试):
sometype v;
v = begin_visitor<Visitor>
.on<MyTypeWithSubnodes>([&v](MyTypeWithSubnodes& x) {
for (auto& subnode : x.subnodes) {
subnode.accept(v);
}
);
话虽如此,我认为“内联访客”的整个概念过于复杂和误导。它使一个简单的概念变得复杂,将比普通访问者实现更低的性能(因为编译器更难以优化),会增加编译时间,并且会使错误消息更难以阅读。
如果您真的想要包含函数中的所有内容,则可以使用内部类以更清晰的方式实现相同的效果:
void my_func() {
class MyVisitor : public Visitor {
void visit(Triangle& t) { /* ... */ }
void visit(Square& s) { /* ... */ }
};
MyVisitor vis;
/* ... do things with vis ... */
}
你唯一没有得到的是直接访问局部变量,但我认为这不值得牺牲可读性。