我正在尝试编写一个c ++ lambda函数,并且不想使用auto
作为类型。目前它看起来像:
#include <iostream>
int main() {
// Sends the address of an integer to a function which prints out the contents;
auto print_int = [](int* a) {std::cout << *a << std::endl;};
int a;
a = 3;
print_int(&a);
return 0;
}
但是,我想将auto
更改为std::function<void(int)>
,但不确定如何。
似乎相关,但我不确定如何适应它。感谢。
答案 0 :(得分:7)
Lambda用于auto
或模板参数。你永远不知道lambda的类型,你不能输入它。每个lambda都有自己独特的类型。即使您知道该类型的名称,它们的类型名称通常也包含类型名称中禁止的字符。
为什么lambda有自己的类型?因为实际上,编译器创建了一个类似于这样的类:
struct /* unnamed */ {
// function body
auto operator()(int* a) const {
std::cout << *a << std::endl;
}
} print_int; // <- instance name
此代码非常接近等效(我省略了转换运算符)。 如您所见,您已经使用auto,因为lambdas正在推断返回类型。
有些人会说使用std::function<void(int*)>
,但我不同意。 std::function
是围绕任何可调用的多态包装器。由于lambdas是可调用类型,因此它们适合它。换句话说,它的工作方式与std::any
非常相似,但有一个调用操作符。它会在你的应用程序中产生开销。
那你该怎么办?
使用auto
! auto
也不错。实际上,它甚至可以使您的代码更快,并减少不必要的输入。如果你对auto
感到不舒服,那么你不应该这样做! auto
很棒,特别是如果你没有选择;)
事实上,您可以通过使用模板参数来避免使用auto
:
template<typename F, typename Arg>
void parametric_print(F function, Arg&& arg) {
function(std::forward<Arg>(arg));
}
然后像这样使用它:
int main() {
int a = 3;
parametric_print([](int* a) {std::cout << *a << std::endl;}, &a);
}
你去了,没有auto
!但是,使用与auto
相同的规则推导出模板参数。实际上,概念被C ++ 20标准接受,具有简洁的功能模板。您可以编写相同的函数模板,如下所示:
// C++20
void parametric_print(auto function, auto&& arg) {
function(std::forward<decltype(arg)>(arg));
}
正如Oktalist所提到的,如果标准中接受了概念,那么您可以将auto
替换为Callable
:
Callable print_int = [](int* a) { std::cout << *a << std::endl; };
但它不会产生不同的类型,它只是在推断类型时强制执行一些规则。
答案 1 :(得分:2)
你走了:
int a;
[](int* a) {std::cout << *a << std::endl;}(&a);
未使用auto
。
但是,我想将自动更改为
std::function<void(int)>
,但不确定如何。
这当然是可能的。 std::functional
有一个模板化的转换构造函数。你只需将lambda传递给构造函数,那就是它的全部内容。此外,您需要修复参数类型,因为您的lambda需要int*
,而不是int
(这是auto
自动修复的错误< / em>的)。
std::function<void(int*)> print_int = [](int* a) {std::cout << *a << std::endl;};
但请注意,这有两个缺点。
std::function
wrapper是一个间接层,它隐藏了可调用对象的实际类型。此包装层会增加运行时开销并阻止一些优化。答案 2 :(得分:1)
lambda有自己的未命名类型。
您可以将您的lambda转换为std::function<void(int*)>
(或无捕捉的lambda到void (*)(int*)
)。
您可以明确地创建您的仿函数,以便为其命名,例如:
class Print_int
{
public:
void operator()(int* a) const {std::cout << *a << std::endl;}
};
然后
Print_int print_int;