Why does my lambda function work with 'this' and not a node name?

If I use CallFunc with a lambda expression, it works when passing ‘this’:

CallFunc::create([ this ] () { this->mySprite->doSomething(); }) // ok

However, if ‘this’ (a layer subclass) has a variable and I call the same thing I get an error:

CallFunc::create([ mySprite ] () { mySprite->doSomething(); })

The error I get is on the CallFunc line:

'mySprite' in capture list does not name a variable

You can try the following code in the HelloWorld Project.

    sprite->setTag(100);
    
    if(true)
    {
        this->runAction(Sequence::create(DelayTime::create(2),
                                     CallFunc::create([sprite](){sprite->removeFromParent();}),
                                     nullptr));
    }
    else
    {
        this->runAction(Sequence::create(DelayTime::create(2),
                                     CallFunc::create([this](){this->getChildByTag(100)->removeFromParent();}),
                                     nullptr));
    }

Lambdas can only capture identifiers. You could alias it however.

auto* alias = mySprite;
CallFunc::create([ alias ] () { alias->doSomething(); })

also a reminder that if the sprite could get removed and released before the callfunc’s lambda is executed you will want to protect it with a retain/release

auto* alias = mySprite;
alias->retain();
CallFunc::create([ alias ] () { 
   alias->doSomething(); 
   alias->release(); // or safe_release
})

See this answer:

The standard states that a capture must be &, =, this, an identifier, or an identifier preceeded by &.
Since this->mySprite is not an identifier, but a “class member access expression”. the compiler is correct when rejecting your snippet.

1 Like

Thanks @stevetranby for the detailed explanation.