Reputation: 6856
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
Upvotes: 4
Views: 1224
Reputation: 13424
[...] is it possible to tell the compiler to inline the lambda argument since it's known at compile time?
Highly unlikely (in other words - no), which is mainly because you use std::function
which, due to it's implementation's nature, uses type erasure and achieves this with dynamic allocation. When you call it, a virtual call is made so there is a jump. In order to inline the code, you may switch to:
template <typename Callback>
inline void readandrun(Callback callback) {
int i;
i = 1;
callback(i);
}
That way, the lambda's exact type is deduced and the code is perfectly fine for inlineability.
Remember - lambda's type is never std::function
. It's (the std::function
) merely a wrapper around a callable with actual type erased.
Upvotes: 10
Reputation: 22219
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);
}
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.
Upvotes: 5