• Advertisement

Capturing "this" in a lambda function

Recommended Posts

Hi guys, I'm having some trouble understanding what this code is doing, can you give me a hand ?_? 

Code by Vittorio Romeo, you can find the whole thing here

So the part I'm having trouble with is this one:

 // Another useful method will allow the user to execute arbitrary
    // code on all entities of a certain type.
    template <typename T, typename TFunc>
    void forEach(const TFunc& mFunc)
    {
        // Retrieve all entities of type `T`.
        auto& vector(getAll<T>());

        // For each pointer in the entity vector, simply cast the
        // pointer to its "real" type then call the function with the
        // casted pointer, dereferenced.
        for(auto ptr : vector) mFunc(*reinterpret_cast<T*>(ptr));
}

and

 // The game logic is now much more generic: we ask the
                // manager to give us all instances of a certain game
                // object type, then we run the collision functions.
                // This is very flexible as we can have any number
                // of balls and bricks, and adding new types of game
                // objects is extremely easy.
                manager.forEach<Ball>([this](auto& mBall)
                    {
                        manager.forEach<Brick>([this, &mBall](auto& mBrick)
                            {
                                solveBrickBallCollision(mBrick, mBall);
                            });
                        manager.forEach<Paddle>([this, &mBall](auto& mPaddle)
                            {
                                solvePaddleBallCollision(mPaddle, mBall);
                            });
});

I get that forEach<T>(Tfunc) retrieves a vector<BaseClass*>&  ,casts every element in it from the BaseClass pointer to a T* and apply the TFunc passed to them, but I kind of get lost, I mean why the lambda passed to it is capturing [this], and even what is [this] in that context...?!

Is it the Game class that owns the manager data member?

Or 'this' is becoming something else inside the forEach function (meaning that it acts inside of it since is a template argument, capturing the "this" inside of forEach, which I believe should be the manager itself?).

And then, I don't see 'this' used anywhere, so...just very confused. Can you help me understand? ^_^

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

Capturing the this pointer is needed if you want the closure defined by the lambda to access member variables on the class that owns the method that the lambda is defined within. The syntax allows access to member variables and methods on the "enclosing object" without actually using the this pointer - just as if the code within the lambda was in a method on the object.

I haven't looked at the code in detail, but is solvePaddleBallCollision a method on whatever class has the method defining these lambdas?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites

No that solve functions are standing alone function, but according to what you say the 'this' capture is then needed to access the 'manager.' which is a member variable of the Game class (the code snippet is from a member function of the Game class). Makes sense, thanks :)

Follow up question is, is capturing 'this' the only way or he could have directly captured the member variable needed, in this case 

[&manager](){}

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
2 hours ago, Oberon_Command said:

I believe you need to capture this if you're capturing by reference. Not sure if that's necessary if you're capturing the member by value.

You could expose only the member variable as well.

#include <functional>
#include <iostream>

struct Integer {
    int a = 0;
};

int main() { 
    Integer integer;
    int &b = integer.a;
    std::cout << integer.a << std::endl;
    const auto lambda = [&b]() { ++b; };
    lambda();
    std::cout << integer.a << std::endl;
};

In the snippet above, I capture the member variable a by reference in the capture list of the lambda. And of course, an instance of a class can thus in a similar fashion create a lambda with references to certain of its member variables in the capture list without adding this.

Edited by matt77hias

Share this post


Link to post
Share on other sites
On 2/6/2018 at 1:01 AM, MarcusAseth said:

Follow up question is, is capturing 'this' the only way or he could have directly captured the member variable needed, in this case 


[&manager](){}

Use (referring to my Minimal Working Example above):

struct Integer {
    int a = 0;
    void f() {
        const auto lambda = [&b(a)]() { ++b; };
        lambda();
    }
};

What you propose would not work:

struct Integer {
    int a = 0;
    void f() {
        const auto lambda = [&a]() { ++a; };
        lambda();
    }
};
error: 'this' cannot be implicitly captured in this context

Damn, I thought these two previous posts would be merged :(

So I add a summary:

struct Integer {
    int a = 0;
    void f() {
        const auto lambda = [&b(a)]() { ++b; };
        lambda();
    }
};

int main() { 
    Integer integer;
    int &b = integer.a;
    std::cout << integer.a << std::endl;
    const auto lambda = [&b]() { ++b; };
    lambda();
    std::cout << integer.a << std::endl;
    integer.f();
    std::cout << integer.a << std::endl;
};

Try It Online

Edited by matt77hias

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By LifeArtist
      Good Evening,
      I want to make a 2D game which involves displaying some debug information. Especially for collision, enemy sights and so on ...
      First of I was thinking about all those shapes which I need will need for debugging purposes: circles, rectangles, lines, polygons.
      I am really stucked right now because of the fundamental question:
      Where do I store my vertices positions for each line (object)? Currently I am not using a model matrix because I am using orthographic projection and set the final position within the VBO. That means that if I add a new line I would have to expand the "points" array and re-upload (recall glBufferData) it every time. The other method would be to use a model matrix and a fixed vbo for a line but it would be also messy to exactly create a line from (0,0) to (100,20) calculating the rotation and scale to make it fit.
      If I proceed with option 1 "updating the array each frame" I was thinking of having 4 draw calls every frame for the lines vao, polygons vao and so on. 
      In addition to that I am planning to use some sort of ECS based architecture. So the other question would be:
      Should I treat those debug objects as entities/components?
      For me it would make sense to treat them as entities but that's creates a new issue with the previous array approach because it would have for example a transform and render component. A special render component for debug objects (no texture etc) ... For me the transform component is also just a matrix but how would I then define a line?
      Treating them as components would'nt be a good idea in my eyes because then I would always need an entity. Well entity is just an id !? So maybe its a component?
      Regards,
      LifeArtist
    • By nickyc95
      Hi.
      I'm kind of late to this party but I thought I would ask anyway as I haven't found a concrete answer.
       
      When creating a game engine, when should you choose one methodology over another (more specifically OOP and DOD)? Which areas benefit from DOD? Which areas benefit from OOP? Do people typically mix multiple methodologies throughout a project? I.e. certain sub-systems created in one, and others in the another?  
      DOD - Data Oriented Design
      OOP - Object Oriented Design
       
      Pretty simple
      Thanks
    • By Estra
      Memory Trees is a PC game and Life+Farming simulation game. Harvest Moon and Rune Factory , the game will be quite big. I believe that this will take a long time to finish
      Looking for
      Programmer
      1 experience using Unity/C++
      2 have a portfolio of Programmer
      3 like RPG game ( Rune rune factory / zelda series / FF series )
      4 Have responsibility + Time Management
      and friendly easy working with others Programmer willing to use Skype for communication with team please E-mail me if you're interested
      Split %: Revenue share. We can discuss. Fully Funded servers and contents
      and friendly easy working with others willing to use Skype for communication with team please E-mail me if you're interested
      we can talk more detail in Estherfanworld@gmail.com Don't comment here
      Thank you so much for reading
      More about our game
      Memory Trees : forget me not

      Thank you so much for reading
      Ps.Please make sure that you have unity skill and Have responsibility + Time Management,
      because If not it will waste time not one but both of us
       

    • By mike44
      typedef struct FontInfo_t* FontHandle;
      MichaelNS::FontMgr m;
      MichaelNS::FontHandle FontGeladen;
      const char *FontPtr;
      start:
      InFileFont.append("Ubuntu-B.ttf");
      FontPtr = InFileFont.c_str();
      FontGeladen = m.loadFont(FontPtr, NULL, NULL, 14, 0);
      stop:
          m.unloadFont(FontGeladen);
          delete FontPtr;
      delete causes a crash. How to unload the class correctly?
      Thanks
    • By Cat's machete
      I need to use global vars,
      So say i have main.cpp file where i #include "globalvars.h"
      In globalvars.h i define
      extern int ppp;
      In globalvars.cpp i put #include "globalvars.h"
      int ppp;
       
       
      Now in main cpp during compilation i get UNDEFINED REFERENCE TO ppp
  • Advertisement