This article (http://accu.org/index.php/articles/2021) introduces a very interesting concept of how to use inline visitors. I liked this approach and gave it a try. However, I encountered some issues.
Unfortunately the implementation is complicated to understand in depth.
Example:
// 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);
I appreciate every comment or hint towards this technique.
Thanks & regards
There is no license given anywhere on the website. Is this sourcecode free to use?
No. But you can ask the authors for a license, and you are certainly allowed to implement your own "inline visitor" using their implementation as inspiration.
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.
The code as given does not do subnode traversal - it has no concept of submodes. You would have to do that in the relevant .on handler, same as you would for a normally implemented visitor. I imagine something like this (untested):
sometype v;
v = begin_visitor<Visitor>
.on<MyTypeWithSubnodes>([&v](MyTypeWithSubnodes& x) {
for (auto& subnode : x.subnodes) {
subnode.accept(v);
}
);
That being said, I think that the entire concept of "inline visitors" is overly complicated and misguided. It makes a simple concept complicated, will achieve lower performance than a normal visitor (because the compiler has a harder time optimizing), will increase compilation times, and will make error messages much more difficult to read.
You can achieve the same effect in a much cleaner way using an inner class if you really want to contain everything inside your function:
void my_func() {
class MyVisitor : public Visitor {
void visit(Triangle& t) { /* ... */ }
void visit(Square& s) { /* ... */ }
};
MyVisitor vis;
/* ... do things with vis ... */
}
The only thing that you do not get is direct access to the local variables, but I don't think that's worth sacrificing readability for.