嵌套Lambda的问题

时间:2013-08-05 00:06:35

标签: c++11 lambda

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

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&gt; c:\ program files(x86)\ microsoft visual studio 11.0 \ _vc \ include \ xutility(3186):错误C2678:二进制'==':找不到哪个运算符带有'的左手操作数' int'(或没有可接受的转换)

我错过了什么?

1 个答案:

答案 0 :(得分:3)

cppreference on std::find and std::find_if

std::find作为第三个参数进行比较,而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的转换,并且没有声明适用于此的比较运算符。