我如何将Lambda表达式传递给C ++模板作为参数 [英] How I can pass lambda expression to c++ template as parameter
问题描述
我有一个接受函数作为参数的模板。
I have a template that accepts a function as an argument.
当我尝试传递lambda表达式时,它不会编译。
When I try to pass a lambda expression it does not compile.
typedef int (*func)(int a);
template <func foo>
int function(int a)
{
foo(a);
}
int test(int a)
{
return a;
}
int main()
{
function<test>(1); // ---> this is ok
auto lambda = [](int a) -> int { return a; };
function<lambda>(1); // ---> this is wrong, why?
return 0;
}
我丢失了什么?
推荐答案
lambda不是函数指针! Lambda是编译器生成的类的实例!
A lambda is not a function pointer! A lambda is an instance of compiler generated class!
但是,未捕获的Lambda可以使用其 operator + $转换为函数指针c $ c>
However, a non capturing lambda may be converted to a function pointer using it's operator+
下面是一个示例:
int main() {
auto lambda = [](int a) { return a; };
func ptr = +lambda; // this would work
return 0;
}
不幸的是, operator +
甚至在您的情况下都不起作用,因为它没有被声明为constexpr,因此您不能在模板参数中使用它。
Sadly, the operator+
won't even work in your case because it has not been declared as constexpr, so you can't use it in a template parameter.
对案例的修复将使用免费功能...直到不接受 N4487 ,您可以
A fix to your case would be to use a free function... until N4487 is not accepted, you can't expect to pass lambda as template parameter.
另一种解决方法是创建自己的仿函数而不是lambda:
Another fix would be to create your own functor instead of a lambda:
struct LambdaType {
constexpr LambdaType() = default;
int operator()(int a) {
return run(a);
}
// this is a non-capturing lambda, the operator can be
// in a static function
static int run(int a) {
return a;
}
};
int main() {
LambdaType lambda;
function<&LambdaType::run>(1); // ---> this is working
return 0;
}
此解决方案不太吸引人,但是如果 LambdaType
隐藏在cpp文件中。
This solution is not quite appealing, but it might be useful if LambdaType
is hidden in a cpp file.
如果您的目标只是编译器能够内联代码,则可以使用模板来传递lambda:
If your goal is only the compiler to be able to inline your code, you can use templates to pass the lambda around:
#include <iostream>
template <typename T>
int function(T foo, int a) {
return foo(a);
}
int main() {
int a;
std::cin >> a;
int b = function([](int a) { return a; }, a);
return b;
}
因为编译器知道 T的类型
的每个实例,一个好的编译器应该能够优化lambda。
Since the compiler knows the type of T
for each instanciation, a good compiler should be able to optimize out the lambda.
使用clang,第三个选项给出了以下汇编:
With clang, the third option gives the following assembly:
main: # @main
pushq %rax
leaq 4(%rsp), %rsi
movl std::cin, %edi
callq std::basic_istream<char, std::char_traits<char> >::operator>>(int&)
movl 4(%rsp), %eax # this is the call to the function
addq $8, %rsp
retq
pushq %rax
movl std::__ioinit, %edi
callq std::ios_base::Init::Init()
movl std::ios_base::Init::~Init(), %edi
movl std::__ioinit, %esi
movl $__dso_handle, %edx
popq %rax
jmp __cxa_atexit # TAILCALL
我使用了 -std = c ++ 14 -Ofast -march = native
作为标志。
这篇关于我如何将Lambda表达式传递给C ++模板作为参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!