C++ 内联 lambda 参数
C++ Inline lambda argument
考虑以下代码
#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;
}
编译
g++ -DLAMBDA -O2 -std=c++17 -S test.cpp -o test_long.S
产生涉及跳转的代码,而
g++ -O2 -std=c++17 -S test.cpp -o test_short.S
不会。哪一种有意义,但是否可以告诉编译器内联 lambda 参数,因为它在编译时已知?我愿意切换编译器,但为了完整性:
$ 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
[...] is it possible to tell the compiler to inline the lambda argument since it's known at compile time?
极不可能(换句话说 - 否),这主要是因为您使用 std::function
,由于其实现的性质,它使用 输入 erasure 并通过 动态分配 实现。当您调用它时,会进行虚拟调用,因此会发生跳转。为了内联代码,您可以切换到:
template <typename Callback>
inline void readandrun(Callback callback) {
int i;
i = 1;
callback(i);
}
这样,lambda 的确切类型就会被推导出来,并且代码非常适合内联性。
记住 - lambda 的类型永远不会 std::function
。它(std::function
)只是一个可调用对象的包装器,实际类型已被擦除。
如果你允许使用函数指针而不是 std::function
作为你的参数,你可以使你的函数 constexpr
:
constexpr void readandrun(void(*callback)(int)) {
int i = 1; // can't use uninitialized variables in constexpr function
callback(i);
}
请注意,只有 non-capturing lambda 可以转换为函数指针。有关捕获 lambda 的信息,请参阅 constexpr
函数有一些限制,但另一方面编译器会尽可能在编译时执行它们。