0

我对 lambdas 的经验还不是很丰富,但我开始非常喜欢它们,并在有意义的地方使用它们,并且我觉得它们是要走的路。

无论如何,我有一个类TreeTree::Visitor该类具有一个名为visit(/*args*/). 该访问者类对所有节点进行递归遍历。通过这个回调,我可以从每个节点收集数据(或者更好的是我可以提取树的路径(这基本上就是我使用这个函数所做的)。

所以我取了一个 lambda,在里面我使用一个类来实现visit回调函数,方法是从Tree::Visitor.

// Tree class, a rough view how it looks
class Tree {

    // ...

    // Visitor class for recursive walking the tree
    class Visitor {
       // 
       void count(/* ... */) {
           // in here the implemented visit(/*args*/) fct is called
       }

       // ...
       void triggerVisit() { 
           // ...
           count(/* ... */);
           // ...
       }

       // visitor callback
       virtual void visit(/* args */) = 0;
    };
};

class A {
    Tree tree;
    PriorityQueue que;

    A() : tree(), que(maxEntries) {}

    // first build the tree ...
    void buildTheTree() {
        tree.buildTree();               
    }

    // walk the tree
    void visitTheTree() {

       std::shared_ptr<Tree::Visitor>(
          [&]()->Tree::Visitor * {

             // this class implements visit(/*args*/)
             class MyVisitor : public Tree::Visitor {
                 A& parent; // pointer to A

                 Myvisitor(A& p) 
                 : Tree::Visitor(p.tree), parent(p) {}      

                 // implementation
                 virtual void visit( /* args */ ) {

                     // ... get somedata 

                     if (/* condition true */) {
                         parent.que.push(somedata);
                     }
                 }  
             };

             return new MyVisitor(*this);

          }()
       )->triggerVisit();

       // get the collected data from que
       while(que.size() > 0) {
          // ...
       }
    }
};

基本上这就是我所拥有的,它可以正常工作。

我有一个que用于存储的优先级队列somedata,它们是n树中得分最高的节点。此时,它que被定义为 class 的成员A,我不喜欢,因为我只需要收集 visitTheTree 成员内部的数据,所以它可能是一个局部变量所以我的问题更多是设计/风格的问题,我感觉我错过了 c++11 标准的一些东西(也许)。

我试图在que里面定义visitTheTree()并使用MyVisitor. 不知何故,这无法正常工作,至少我没有得到我期望的正确/完整的结果。当我将优先级队列变量定义为 A 的成员(就像现在一样)并使用 MyVistor 中的父指针访问它时,我得到了正确的结果,一切都很好。

有没有什么好的方法可以que在 VisitTheTree() 中本地定义,而不是在 A 类中将其定义为成员?我知道我必须将它与构造函数一起传递,因为我无法访问 MyVistor 之外的变量(就像这样)。

顺便说一句,我发现问题C++0x - lambda 表达式确实与 Java 的匿名内部类相同?这接近我遇到的问题/问题。有趣的是约翰内斯的回答。

欢迎任何提示或想法。感谢您的想法和帮助!

4

1 回答 1

0

安德烈亚斯,我真的很想帮助你,但我找不到使用你的设计的方法。我在使用 boost 图形库时遇到了类似的情况,我做了以下操作(希望对您有所帮助):

  • 访问者有一个std::function<RET (/*args*/>成员,用于在您访问的每个节点上执行操作。我还会将此函数作为访问者构造函数的参数。
  • 每次你需要访问一些节点时,你都会通过一个新的访问者实例来传递一个新的 lambda 函数作为参数。

我会尝试提供一些例子,

class Tree {
    ...
    typedef std::function<void (/*node and args*/)> visit_fn;

    class Visitor {
        visit_fn& visitor;

        public:
            Visitor( visit_fn f ) : visitor( f ) {}
        ...
    };
};

class A {

    ...

    void visit_tree() {
        que.clear(); // could also be a local queue object

        Visitor vis([&](/*args*/) {
            que.push( some_data ); /*I have que because of & in my lambda*/
        });

        vis.triggerVisit();

        // Her I can use my queue member
    }

};

现在,如果您有一种通用的方式来访问您的元素,您甚至可以将 Functor 传递给您的访问者,从而提供更好的代码重用。

我真的认为您设计中的 lambda 没有使用[&]绑定,从这个意义上说,它可能是一个通用函数,我认为它会更干净、可重用和高效。

于 2013-05-03T16:37:26.193 回答