lambda函数的类型,使用auto

oli*_*rsm 7 c++ lambda types c++11

我正在尝试编写一个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;
}
Run Code Online (Sandbox Code Playgroud)

但是,我想改变auto类似std::function<void(int)>但不确定如何.答案

似乎相关,但我不知道如何适应它.谢谢.

Gui*_*cot 8

Lambdas旨在与任一auto模板参数一起使用或作为模板参数使用.你永远不知道lambda的类型,你不能输入它.每个lambda都有自己独特的类型.即使您知道该类型的名称,它们的类型名称通常也包含类型名称中禁止的字符.

为什么lambda有自己的类型?因为实际上,编译器创建了一个类似于这样的类:

struct /* unnamed */ {

    // function body
    auto operator()(int* a) const {
        std::cout << *a << std::endl;
    }

} print_int; // <- instance name
Run Code Online (Sandbox Code Playgroud)

这段代码非常接近等价(我省略了转换运算符).如您所见,您已经使用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));
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

int main() {
    int a = 3;
    parametric_print([](int* a) {std::cout << *a << std::endl;}, &a);
}
Run Code Online (Sandbox Code Playgroud)

你去,不auto!但是,模板参数的推导与使用相同的规则auto.实际上,概念被C++ 20标准接受,具有简洁的功能模板.您可以像这样编写相同的函数模板:

// C++20
void parametric_print(auto function, auto&& arg) {
    function(std::forward<decltype(arg)>(arg));
}
Run Code Online (Sandbox Code Playgroud)

正如Oktalist所提到的,如果标准中接受了概念,那么您可以替换autoCallable:

Callable print_int = [](int* a) { std::cout << *a << std::endl; };
Run Code Online (Sandbox Code Playgroud)

但它不会产生不同的类型,它只是在推断类型时强制执行一些规则.