简体   繁体   English

在 lambda 中捕获 std::array

[英]Capture std::array in lambda

I was trying to test some simple C-style sort functions.我试图测试一些简单的 C 风格排序函数。 In the driver program, I wrote something like this:在驱动程序中,我是这样写的:

int main()
{
    std::array<int, 8> A = { 1, 0, 4, 5, 7, 2, 9, 3 };
    auto lambda = [&A](const std::function<void(int *A, int n)> &sorting_alg) {
        int n = A.size();
        sorting_alg(A.data(), n);
        std::cout << "=> ";
        print(A.data(), n);
        std::cout << std::endl;
    };

    auto do_bubble_sort = std::bind(lambda, bubble_sort);
    auto do_selection_sort  = std::bind(lambda, selection_sort);
    auto do_insertion_sort  = std::bind(lambda, insertion_sort);

    std::cout << "Bubble Sort :" << std::endl;
    do_bubble_sort();
    std::cout << "Selection Sort :" << std::endl;
    do_selection_sort();
    std::cout << "Insertion Sort :" << std::endl;
    do_insertion_sort();

    return 0;
}

I had the bind code, to which I could pass A to copy, but it confines my lambda to size=8 , which I want to avoid.我有绑定代码,我可以将A传递给它进行复制,但它将我的 lambda 限制为size=8 ,这是我想避免的。 Is it possible to achieve this without using something like std::vector , etc?是否可以在不使用std::vector等的情况下实现这一点? As soon I change capture method of A to value-capture, it doesn't compile anymore.一旦我将A捕获方法更改为值捕获,它就不再编译了。 I wanted to use copies for the array, to test all sorting functions.我想为数组使用副本,以测试所有排序功能。 Why can't I capture std::array by value?为什么我不能按值捕获std::array Why then size-inference works for reference case?为什么尺寸推断适用于参考案例?

The operator() of a lambda is const by default.默认情况下,lambda 的operator()const That means you can't modify any members of the lambda (it's captures).这意味着您不能修改 lambda 的任何成员(它是捕获)。 When you capture by reference, this means you can't change the reference to refer to something else, but since you can't do that already it basically means nothing.当您按引用捕获时,这意味着您不能将引用更改为引用其他内容,但由于您已经无法这样做,因此基本上没有任何意义。 When you capture by value it makes that value const , which means you can no longer modify like your sorting method requires (you need data to return a non-const pointer).当您按值捕获时,它会使该值成为const ,这意味着您不能再像排序方法要求的那样进行修改(您需要data来返回非常量指针)。

To get around this you can use the mutable keyword to make the lambda's operator() not const .为了解决这个问题,您可以使用mutable关键字使 lambda 的operator()不是const That would look like那看起来像

auto lambda = [A](const std::function<void(int *A, int n)> &sorting_alg) mutable {
    int n = A.size();
    sorting_alg(A.data(), n);
    std::cout << "=> ";
    print(A.data(), n);
    std::cout << std::endl;
};

You can capture by value, but you have to change the lambda to a mutable one.您可以按值捕获,但必须将 lambda 更改为可变的。

When you capture by value, the captures are const by default.当您按值捕获时,捕获默认为 const。 You can mark it mutable or make a copy locally:您可以将其标记为可变或在本地复制:

auto lambda = [A](const std::function<void(int *A, int n)> &sorting_alg) {
    auto ALocal = A;
    int n = ALocal.size();
    sorting_alg(ALocal.data(), n);
    std::cout << "=> ";
    print(ALocal.data(), n);
    std::cout << std::endl;
};

Live example活生生的例子

This has the advantage of making the lambda callable multiple times.这具有使 lambda 可多次调用的优点。

You can do this with capture by reference too.您也可以通过引用捕获来做到这一点。

You can alternatively make the lambda mutable, but callable only once:您也可以使 lambda 可变,但只能调用一次:

auto lambda = [A](const std::function<void(int *A, int n)> &sorting_alg) mutable {
    int n = A.size();
    sorting_alg(A.data(), n);
    std::cout << "=> ";
    print(A.data(), n);
    std::cout << std::endl;
};

The problem is that the operator() of the lambda function is const -qualified by default.问题是 lambda 函数的operator()默认情况下是const限定的。 This means that the values captured by value are const -qualified in the lambda body.这意味着 value 捕获的值在 lambda 主体中是const限定的。 In your code, you are trying to invoke std::function with a non- const pointer to int initialized from the captured array, which is const .在您的代码中,您尝试使用从捕获的数组( const初始化的指向int的非const指针调用std::function

To fix this you need to mark your lambda as mutable so that the generated operator() is no longer const -qualified:要解决此问题,您需要将 lambda 标记为mutable以便生成的operator()不再是const限定的:

auto lambda = [A](const std::function<void(int *A, int n)> &sorting_alg) mutable {
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM