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

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

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

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

感谢和问候

最佳答案

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

没有。但是您可以向作者索取许可,并且您当然可以使用他们的实现作为灵感来实现您自己的“内联访问者”。

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);
    }
);

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

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

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/

相关文章:

c++ - Prims算法节点优先级

c++ - 访问被参数隐藏的数据成员

c++ - 编写一个只接受文字 `0` 或文字 `1` 作为参数的函数

c++ - 是否保证 std::swap(x, x) 保持 x 不变?

c# - 工厂模式应该放在 DDD 中的什么位置?

java - 使用 sax 解析器实现的设计问题

c++ - 为什么在使用 "using namespace std;"和 "bits/stdc++.h"时会在此代码中出现错误?

c++ - Windows:最大化周围/像任务栏一样对待我的窗口?

c++ - 对于不可复制类型的范围循环,是否可能?

c# - "using"构造和异常处理