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

时间:2016-04-13 13:20:30

标签: c++ c++11 design-patterns licensing visitor

本文(http://accu.org/index.php/articles/2021)介绍了如何使用内联访问者的一个非常有趣的概念。我喜欢这种方法并试一试。但是,我遇到了一些问题。

  • 网站上没有任何许可证。这个源代码可以免费使用吗?
  • 本文中的示例仅使用clang 3.8.0(不是使用gcc 5.3.1)进行编译,并且仅进行一些小修改(更改" auto v = begin_visitor ..." to&#34 ; auto v = begin_visitor()...")。
  • 假设我的代码包含非平面图(例如AST)。图中的一些节点包含对子节点的引用。如果我的访问者遍历这样的节点,我想指定必须如何遍历子节点的顺序。这种实现甚至可以实现吗?

不幸的是,实施起来很难深入理解。

示例:

// 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;问候

1 个答案:

答案 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 ... */
}

你唯一没有得到的是直接访问局部变量,但我认为这不值得牺牲可读性。