Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I failing to capture the "this" pointer by a lambda?

Consider the following code:

class A
{
public:
    void foo()
    {
        auto functor = [this]() 
            {
                A * a = this;
                auto functor = [a]() // The compiler won't accept "this" instead of "a"
                    {
                        a->bar();
                    };
            };
    }

    void bar() {}
};

In VC2010, using this instead of a lead to compilation errors. Among others:

1>main.cpp(20): error C3480: '`anonymous-namespace'::<lambda0>::__this': a lambda capture variable must be from an enclosing function scope
1>main.cpp(22): error C3493: 'this' cannot be implicitly captured because no default capture mode has been specified

Which I don't understand. Does it mean it doesn't know if it should use a reference or copy it? When trying to use &this to force referencing, it also says:

1>main.cpp(20): error C3496: 'this' is always captured by value: '&' ignored

The temporary is not that annoying, but for the sake of curiosity, is there a way to get rid of it? What goes on when this is given to a lambda?

like image 707
Gabriel Avatar asked Oct 19 '11 19:10

Gabriel


2 Answers

This appears to be a compiler bug in VS2010. I was able to make it work by letting the inner lambda implicitly capture this:

class A
{
public:
    void foo()
    {
        auto functor = [this]() 
        {
            auto functor = [=]()
            {
                bar();
            };
        };
    }

    void bar() {}
};

When trying to use &this to force referencing, it also says:

1>main.cpp(20): error C3496: 'this' is always captured by value: '&' ignored

this can only be captured by value. [=] and [&] both capture it by value.

What goes on when this is given to a lambda?

I don't know but it must be something special because you can't use this in a lambda as a pointer to the lambda object. Anything else captured becomes a private member of the lambda so presumably this does too but there's some special handling on usage.

like image 114
David Avatar answered Nov 14 '22 04:11

David


This is a known bug with the Visual Studio 2010 compiler (as referenced by Frédéric Hamidi's comment).

You have to explicitly capture this to pass it to another lamba's capture specification. This also applies to local variables declared outside the lambda's enclosing lambda, even with a [&] capture specification.

like image 43
MSN Avatar answered Nov 14 '22 05:11

MSN