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

  • 网站上没有授予任何许可证。这个源代码可以免费使用吗?
  • 本文中的示例仅使用clang 3.8.0(不适用于gcc 5.3.1)进行编译,并且仅进行了一些小的修改(将“auto v = begin_visitor ...”更改为“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);
    

    我感谢对此技术的所有评论或提示。

    感谢和问候

    最佳答案



    不会。但是您可以向作者索取许可证,当然可以允许您使用自己的“在线访问者”作为实现的灵感。



    给出的代码不进行子节点遍历-它没有子模式的概念。您必须在相关的.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 ... */
    }
    

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

    关于c++ - 在现代C++中为层次图定义内联访客,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36599742/

    10-10 14:19