在现代 C++ 中为层次图定义访问者内联

Defining Visitors Inline in Modern C++ for Hierarchical Graphs

这篇文章 (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); 

我感谢对这项技术的每一条评论或提示。

感谢和问候

There is no license given anywhere on the website. Is this sourcecode free to use?

没有。但是您可以向作者索取许可,并且您当然可以使用他们的实现作为灵感来实现您自己的 "inline visitor"。

Some of those nodes in the graph hold references to subnodes. If my visitor traverse such a node, I would like to specify the order of how the subnodes have to be traversed.

给定的代码不进行子节点遍历——它没有子模式的概念。您必须在相关的 .on 处理程序中执行此操作,就像您对正常实现的访问者所做的一样。我想象这样的事情(未经测试):

sometype v;
v = begin_visitor<Visitor>
    .on<MyTypeWithSubnodes>([&v](MyTypeWithSubnodes& x) {
        for (auto& subnode : x.subnodes) {
            subnode.accept(v);
    }
);

话虽这么说,但我认为 "inline visitors" 的整个概念过于复杂且具有误导性。它使一个简单的概念变得复杂,将获得比普通访问者更低的性能(因为编译器更难优化),将增加编译时间,并使错误消息更难阅读。

如果您真的想在函数中包含所有内容,则可以使用内部 class 以更简洁的方式实现相同的效果:

void my_func() {
  class MyVisitor : public Visitor {
    void visit(Triangle& t) { /* ... */ }
    void visit(Square& s) { /* ... */ }
  };
  MyVisitor vis;
  /* ... do things with vis ... */
}

唯一不能直接访问局部变量,但我认为不值得为此牺牲可读性。