Answered by:
Adding a lambda capture breaks build

Question
-
I have a functor "SceneNodeWalk" below, which is used in the start of a DeleteTree function.
The call to SceneNodeWalk::operator() in DeleteTree with an empty lambda capture iterates the tree fine, and every node is hit.
Now, I want to use the "nodes" vector in the second set of code. If I change the lambda introducer to [=], or [&], or anything other than [], the compiler complains that SceneNodeWalk::operator() cannot be called with the given argument list.
Any clues on how to make the capture work? Is it a problem with my definition of the functor?
class SceneNodeWalk
{
public:
SceneNodeWalk(SceneNode* walkStartNode);
SceneNode* operator()(void (*nodeFunction)(SceneNode* node, WalkParams &walkParams));
private:
SceneNode* m_WalkRootNode;
};
void SceneNode::DeleteTree(SceneNode* rootNode)
{
std::vector<SceneNode*> nodes;
SceneNodeWalk walkItor(rootNode);
walkItor([] (SceneNode* node, WalkParams& walkParams)
{
//nodes.push_back(node);
});
}
Jim Tomasko
Wednesday, August 1, 2012 11:54 PM
Answers
-
Only a lambda which has no captures is directly convertible to a function pointer. When you capture something, conceptually, you can think of it something like this:
class MyFunctor { public: MyFunctor(SceneNode *captureThis) : _this(captureThis) { } void operator()(SceneNode * node, WalkParams& walkParams) { _this->nodes.push_back(node); } private: SceneNode *_this; };
Here, you wouldn't expect to be able to convert MyFunctor::operator() to a raw function pointer as declared ( void(*)(SceneNode*, WalkParams&) ). It's the same thing with the lambda.
If you want the function to be able to take such, you can declare it in several ways:
// // template: // // FUNC satisfies: void operator(SceneNode*, WalkParams&) template<typename FUNC> void operator()(const FUNC& func) { ... } // // std::function: // void operator()(std::function<void(SceneNode*, WalkParams&)> func) { ... }
- Marked as answer by James Tomasko Thursday, August 2, 2012 4:47 PM
Thursday, August 2, 2012 4:44 PM
All replies
-
I get a clean compile, but an intellisense error. The compiler always wins any conflicts.Thursday, August 2, 2012 12:06 AMModerator
-
Ok, I'll go with the intellisense error, but if I ignore it, I can compile, but then if I add anything in the lambda introducing I can not compile. I have tried [=], [nodes], and even [&] (with small rework)... no matter what I do, my original code will not compile if I uncomment the "nodes.push_back(node)" line, and attempt to pass in "nodes".
Original question still stands.
Jim Tomasko
Thursday, August 2, 2012 1:32 AM -
Only a lambda which has no captures is directly convertible to a function pointer. When you capture something, conceptually, you can think of it something like this:
class MyFunctor { public: MyFunctor(SceneNode *captureThis) : _this(captureThis) { } void operator()(SceneNode * node, WalkParams& walkParams) { _this->nodes.push_back(node); } private: SceneNode *_this; };
Here, you wouldn't expect to be able to convert MyFunctor::operator() to a raw function pointer as declared ( void(*)(SceneNode*, WalkParams&) ). It's the same thing with the lambda.
If you want the function to be able to take such, you can declare it in several ways:
// // template: // // FUNC satisfies: void operator(SceneNode*, WalkParams&) template<typename FUNC> void operator()(const FUNC& func) { ... } // // std::function: // void operator()(std::function<void(SceneNode*, WalkParams&)> func) { ... }
- Marked as answer by James Tomasko Thursday, August 2, 2012 4:47 PM
Thursday, August 2, 2012 4:44 PM