Я еще не очень разбираюсь с лямбдами, но я начинаю их очень любить и использую там, где это имеет смысл, и где я чувствую, что это путь.
Во всяком случае, у меня есть класс Tree
это имеет Tree::Visitor
класс с одной виртуальной функцией обратного вызова visit(/*args*/)
, Этот класс Visitor выполняет рекурсивный обход всех узлов. С помощью этого обратного вызова я могу собирать данные с каждого узла (или, что лучше, я могу извлекать пути из дерева (что в основном и делает с этой функцией).
Поэтому я беру лямбду и внутри я использую класс для реализации 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
определяется как член класса A
, что мне не нравится, потому что мне просто нужно собрать данные внутри члена visitTheTree, так что это может быть скорее локальная переменная
Так что мой вопрос больше относится к дизайну / стилю, и у меня есть ощущение, что я что-то упускаю из-за стандарта c ++ 11 (возможно).
Я пытался определить que
внутри visitTheTree()
и передать его с конструктором MyVisitor
, Почему-то это не работает правильно, по крайней мере, я не получаю правильные / полные результаты, которые я ожидаю. Когда я определяю переменную очереди Priority как член A (как сейчас) и обращаюсь к ней с помощью родительского указателя в MyVistor, я получаю правильные результаты, и все в порядке.
Есть ли хороший способ определить que
локально в VisitTheTree () вместо определения его в классе A как члена? Я знаю, что должен передать его конструктору, так как не могу получить доступ к переменным вне MyVistor (просто так).
Кстати, я нашел вопрос C ++ 0x — лямбда-выражение выглядит так же, как анонимный внутренний класс Java? которая приближается к проблеме / вопросу, который у меня есть. Интересен ответ от Йоханнеса.
Любые намеки или идеи будут приветствоваться. Спасибо за ваши мысли и помощь!
Андреас, я бы очень хотел помочь тебе, но я не вижу способа сделать это, используя твой дизайн. У меня была похожая ситуация с использованием библиотеки графов буста, и я сделал следующее (надеюсь, это поможет вам):
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 вашему посетителю, что обеспечит лучшее повторное использование кода.
Я действительно думаю, что лямбда в вашем дизайне не использует [&]
связывание, и в этом смысле может быть общей функцией, которая, я думаю, будет более чистой, многоразовой и эффективной.
Других решений пока нет …