Warning! Some information on this page is older than 5 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Sun

21

Oct 2012

Much can be said about theory behind lambda expressions, but lambdas in C++ - this new feature of C++11 supported by Visual C++ 2010, 2012, as well as other new compilers - can be explained very simply by following example. Today I wanted to write code that would sort a vector of pointers to entities in my 3D scene by distance from the camera, to ensure correct rendering of translucent objects.

std::vector<CEntity*> entitiesToRender;

vec3 cameraEyePos;

vec3 cameraForwardDir;

Vector in world space pointing forward from the camera - towards its positive Z axis - can be extracted from 3rd column of the view matrix. Dot product between this vector and a vector from camera position to object position gives length of the projection of one vector onto the other, which is the distance from the camera. But that's not the point here.

If you use STL, you know it's convenient to sort a vector using std::sort algorithm. Except if the contained type does not have operator< or you don't want it to be used (like here, as it would just compare pointers), you have to write a functor to compare elements. Lambda simplifies this task:

std::sort(

entitiesToRender.begin(),

entitiesToRender.end(),

[=](CEntity* lhs, CEntity* rhs)

{

return

dot(lhs->GetPosition() - cameraEyePos, cameraForwardDir) >

dot(rhs->GetPosition() - cameraEyePos, cameraForwardDir);

});

This code is equivalent to the traditional, more verbose version using functor:

class CompareFunctor

{

public:

CompareFunctor(const vec3& cameraEyePos, const vec3& cameraForwardDir) :

m_CameraEyePos(cameraEyePos),

m_CameraForwardDir(cameraForwardDir)

{

}

bool operator()(CEntity* lhs, CEntity* rhs) const

{

return

dot(lhs->GetPosition() - m_CameraEyePos, m_CameraForwardDir) >

dot(rhs->GetPosition() - m_CameraEyePos, m_CameraForwardDir);

}

private:

vec3 m_CameraEyePos;

vec3 m_CameraForwardDir;

};

std::sort(

entitiesToRender.begin(),

entitiesToRender.end(),

CompareFunctor(cameraEyePos, cameraForwardDir));

Parameters of lambda inside () are data passed to every call, like parameters of operator() in the functor. Inside [] we can specify what parameters are captured from the current context (local variables), which is equivalent to storing them as member variables inside the functor. [=] means capturing all necessary parameters by value, which are cameraEyePos and cameraForwardDir in this case. [&] would remember them by reference.

Copyright © 2004-2019