0

私はまだラムダの経験があまりありませんが、ラムダがとても好きになり始め、意味のある場所や、ラムダが進むべき道だと感じた場所で使用しています。

とにかく、と呼ばれる1つの仮想コールバック関数を持つクラスTreeを持つクラスがあります。その Visitor クラスは、すべてのノードを再帰的にウォークします。このコールバックを使用すると、各ノードからデータを収集できます (または、ツリーのパスを抽出できます (これは基本的にこの関数で行うことです))。Tree::Visitorvisit(/*args*/)

そのため、ラムダを取得し、内部でクラスを使用して、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を格納するために使用するプライオリティ キューがあります。これは、ツリーsomedatan上位スコアのノードです。現時点でqueは、それは class のメンバーとして定義されていますがA、これは嫌いです。なぜなら、visitTheTree メンバー内のデータを収集する必要があるだけなので、むしろローカル変数である可能性があるため、私の質問はデザイン/スタイルの問題であり、私はC ++ 11標準で何かが恋しいと感じています(おそらく)。

que内部で定義visitTheTree()して のコンストラクタで渡そうとしましたMyVisitor。どういうわけか、これは正しく機能していません。少なくとも、期待する適切な/完全な結果が得られません。Priority キュー変数を A のメンバーとして (現在のように) 定義し、MyVistor で親ポインターを使用してアクセスすると、適切な結果が得られ、すべて問題ありません。

queクラス A でメンバーとして定義する代わりに、VisitTheTree() でローカルに定義する良い方法はありますか? MyVistor の外部の変数にアクセスできないため (このように)、コンストラクターで渡す必要があることはわかっています。

ところで、C++0x - lambda expression does look same as Java's anonymous inner class?という質問を見つけました。これは、私が抱えている問題/質問に近いものです。興味深いのは、ヨハネスからの答えです。

ヒントやアイデアは大歓迎です。あなたの考えと助けをありがとう!

4

1 に答える 1

0

アンドレアス、私は本当にあなたを助けたいのですが、あなたのデザインを使ってそれを行う方法がわかりません. ブースト グラフ ライブラリを使用して同様の状況が発生し、次のようにしました (お役に立てば幸いです)。

  • Visitor には、std::function<RET (/*args*/>アクセスするすべてのノードでアクションを実行するために使用されるメンバーがあります。また、この関数をビジター コンストラクターのパラメーターにします。
  • いくつかのノードにアクセスする必要があるたびに、引数として新しいラムダ関数を渡して、ビジターの新しいインスタンスを通過します。

私はいくつかの例を提供しようとしますが、

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 を Visitor に渡すこともでき、コードの再利用が向上します。

あなたのデザインのラムダは[&]バインディングを使用していないと本当に思います。この意味で、よりクリーンで再利用可能で効率的な一般的な機能になる可能性があります。

于 2013-05-03T16:37:26.193 に答える