Search code examples
c++lambdainline

C++ Inline lambda argument


Consider the followng code

#include <iostream>
#include <functional>

using namespace std;

inline void readandrun(function<void(int)> callback) {
    int i;
    i = 1;
    callback(i);
}

int main(int argc, char *argv[])
{
#ifdef LAMBDA
    readandrun([](int i){ printf("the read number is: %d\n",i);});
#else
    int i;
    i = 1;
    printf("the read number is: %d\n",i);
#endif
    return 0;
}

Compiling with

g++ -DLAMBDA -O2 -std=c++17 -S test.cpp -o test_long.S 

Yields code involving jumps while

g++ -O2 -std=c++17 -S test.cpp -o test_short.S 

Does not. Which kind of makes sense but is it possible to tell the compiler to inline the lambda argument since it's known at compile time? I would be willing to switch compilers but for completeness:

$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Solution

  • If you can allow to take function pointer instead of std::function as your argument, you can make your function constexpr:

    constexpr void readandrun(void(*callback)(int)) {
        int i = 1; // can't use uninitialized variables in constexpr function
        callback(i);
    }
    

    See the assembly online

    Note that only non-capturing lambdas can be converted to function pointers. For capturing lambdas see Fureeish's answer. Also, constexpr functions have some limitations, but on the other hand compiler will execute them at compile time if possible.