【问题标题】:Trouble with Nested Lambdas嵌套 Lambda 的问题
【发布时间】:2013-08-05 08:59:12
【问题描述】:

我可能在这里犯了一些基本错误,但给出:

std::array<int, 3> arr = { 1, 2, 3 };
std::vector<int> vecint;
vecint.push_back(1);
vecint.push_back(2);

这是将 arr 中的元素与 vecint 中的元素进行比较的一种明显方法。

std::for_each(vecint.begin(), vecint.end(), [&arr](int vecvalue) {
    for (auto arritr = arr.begin(); arritr != arr.end(); ++arritr) {
        if (vecvalue == *arritr) {
            std::cout << "found!!! " << vecvalue << "\n";
        }
    }
});

但是,我也可以这样吗?

std::for_each(vecint.begin(), vecint.end(), [&arr](int vecvalue) {
    if (std::find(arr.begin(), arr.end(), [=](int arrval) { return vecvalue == arrval; }) != arr.end()) {
        std::cout << "found!!! " << vecvalue << "\n";
    }
});

后者在VC11编译失败,报错:

1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(3186): error C2678: binary '==' : no operator found which take a left-hand operand of type ' int'(或没有可接受的转换)

我错过了什么?

【问题讨论】:

    标签: c++11 lambda


    【解决方案1】:

    cppreference on std::find and std::find_if

    std::find 采用 value 作为第三个参数进行比较,而 std::find_if 采用 UnaryPredicate(一个函数对象采用一个参数)。您可能只是打错了/想使用std::find_if

    使用std::find_if 对我有用。 Live example.

    #include <array>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    
    int main()
    {
        std::array<int, 3> arr = {{ 1, 2, 3 }};
        std::vector<int> vecint;
        vecint.push_back(1);
        vecint.push_back(2);
    
        std::for_each
        (
            vecint.begin(), vecint.end(),
            [&arr](int vecvalue)
            {
                if (std::find_if(arr.begin(), arr.end(),
                                 [=](int arrval) { return vecvalue == arrval; })
                    != arr.end())
                {
                    std::cout << "found!!! " << vecvalue << "\n";
                }
            }
        );
    }
    

    更简单的版本当然是使用std::find(正确):

        std::for_each
        (
            vecint.begin(), vecint.end(),
            [&arr](int vecvalue)
            {
                if (std::find(arr.begin(), arr.end(), vecvalue) != arr.end())
                {
                    std::cout << "found!!! " << vecvalue << "\n";
                }
            }
        );
    

    然后,当然还有基于范围的循环变体,如果你的编译器支持的话:

    for(auto const& ve : vecint)
    {
        for(auto const& ae : arr)
        {
            if(ve == ae)
            {
                std::cout << "found!!! " << ve << "\n";
            }
        }
    }
    

    如果您的范围已排序,则有更快的算法来获取交集。您可以编写自己的循环来为交集中的每个元素调用一个操作,或者让标准库将交集复制到新容器中:

    #include <iterator> // additionally
    
    std::vector<int> result;
    std::set_intersection(arr.begin(), arr.end(), vecint.begin(), vecint.end(),
                          std::back_inserter(result));
    for(auto const& e : result)
    {
        std::cout << e << std::endl;
    }
    

    幕后发生的事情 - 为什么会出现该错误:

    std::find 定义为(来自 cppreference):

    template< class InputIt, class T >
    InputIt find( InputIt first, InputIt last, const T& value );
    

    value的类型和迭代器的类型是独立的。但是,在std::find 的实现中,必须有这样的比较:

    if(*first == value) { return first; }
    

    此时,您正在比较 int(表达式 *first 的类型)和 lambda(value 的类型)更准确地说:带有闭包类型。这是格式错误的(幸运的是),因为没有从 lambda 转换为 int,并且没有声明适用于此处的比较运算符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-15
      • 1970-01-01
      • 2018-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多