charliepu123
charliepu123

Reputation: 59

"lambda capture" on regular function?

 void startDrawLoop(function<bool()> func)
        {
        while (func()) {} 
        }

    int main() 
    {
    CubeRenderer cubeRenderer; TextRenderer textRenderer;

    // Do initialization

    auto drawLoop=[&] () 
    {
    cubeRenderer.draw();
    textRenderer.draw();
    return true;
    } 
    startDrawLoop(drawLoop);
    return 0;
    } 

If I change drawLoop to a function.

bool drawLoop()
{
// Error, cannot find cubeRenderer
cubeRenderer.draw();
textRenderer.draw();
return true;
} 

How can I make reference to variables outside the function like what lambda captures do?

Upvotes: 1

Views: 148

Answers (2)

M.M
M.M

Reputation: 141554

The equivalent code without the lambda is:

struct lambda_t
{
    CubeRenderer &cubeRenderer;
    TextRenderer &textRenderer;

    bool operator()() const
    { 
        cubeRenderer.draw();
        textRenderer.draw();
        return true;
    }
};


int main() 
{
    CubeRenderer cubeRenderer; TextRenderer textRenderer;
    lambda_t drawLoop{cubeRenderer, textRenderer};
    startDrawLoop(drawLoop);
    return 0;
} 

Whether this is more aesthetic or not is up to you...

Upvotes: 1

Nelfeal
Nelfeal

Reputation: 13269

You can just make drawLoop accept arguments and call it from a lambda that does the capture.

void startDrawLoop(function<bool()> func)
{
    while (func()) {}
}

bool drawLoop(CubeRenderer const& cubeRenderer, TextRenderer const& textRenderer)
{
    cubeRenderer.draw();
    textRenderer.draw();
    return true;
}

int main()
{
    CubeRenderer cubeRenderer; TextRenderer textRenderer;
    startDrawLoop([&]() { drawLoop(cubeRenderer, textRenderer); });
}

You can also use std::bind but I personally find it ugly compared to the lambda.

startDrawLoop(std::bind(drawLoop, std::cref(cubeRenderer), std::cref(textRenderer));

If you want to make the call site as simple as possible, you can make startDrawLoop a template to accept any function with any arguments.

template<typename F, typename... Args>
void startDrawLoop(F func, Args const&... args)
// [...]
startDrawLoop(drawLoop, cubeRenderer, textRenderer);

Demo

Upvotes: 3

Related Questions