Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cost of self-executing C++11 lambdas

Out of a window procedure, I'm writing a switch statement using self-executing lambdas, like this:

LRESULT CALLBACK proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg)
    {
        case WM_CREATE: return [&](WPARAM wp, LPARAM lp) {
            do_something(wp, lp);
            return 0;
        }(wp, lp);

        case WM_SIZE: return [&](HWND hWnd) {
            do_another_thing(hWnd);
            return 0;
        }(hWnd);
    }
    return DefWindowProc(hWnd, msg, wp, lp);
}

I believe compilers are free to optimize it pretty much the way they want, but generally speaking, would a compiler add much boilerplate code to this, comparing to not using these lambdas?

Could a compiler detect the redundant lambdas and remove them?

like image 532
rodrigocfd Avatar asked Oct 04 '16 23:10

rodrigocfd


2 Answers

Optimization questions like this don't have a definite answer in the sense that the optimizer of a compliant compiler can do many, many things. However, in this case most modern optimizers are almost certainly going to inline the lambda, and generate the same assembly whether or not you use the lambda. Because lambdas have a unique type, the compiler can inline easily. Because the lambda is declared and immediately used and never assigned (a more common name is "immediately invoked/evaluated lambda instead of "self executing"), the compiler knows it can only be called once. So typically it will decide to inline.

To be sure, you can look at some assembly: https://godbolt.org/g/QF6WmR. As you can see, the generated assembly in this particular example is identical, but obviously it does not prove the general case.

In general, lambdas are considered low or zero cost abstractions in C++, if you think a lambda makes for the cleanest code then use one. If you need to you can always quickly verify the assembly is the same. Your reason for using the lambda that way is a bit unusual though; I wouldn't really consider code folding to be a good reason. A more common reason to use immediately evaluated lambdas is to be able to use const in situations where otherwise you can't:

int x;
try {
    x = foo();
}
catch (const ExceptionType& e) {
    x = bar();
} 

vs

const auto x = [] () {
    try {
        return foo();
    }
    catch (const ExceptionType& e) {
        return bar();
    }
}();

To persist x in the outside scope in traditional C++ code, we have to declare it first and then assign to it. By using a lambda that returns the value we want, we can declare and assign x at the same time, allowing it to be const.

like image 63
Nir Friedman Avatar answered Sep 24 '22 10:09

Nir Friedman


The question is a bit odd. The compiler doesn't "remove" the lambdas, because the lambdas are in your source code, and the compiler doesn't modify your source code. What it does is emit machine code that produces the behaviour of the program you expressed in source code.

The compiler is free to emit as much or as little machine code as it likes as long as the result behaves the way that your program expresses.

A compiler certainly does not have to emit separate function bodies and jumps/calls between them if it can inline all the code into one place, and that is a commonly applied optimization.

like image 40
Kerrek SB Avatar answered Sep 24 '22 10:09

Kerrek SB