2013-08-05 8 views
0

Я, вероятно, сделать некоторые элементарные ошибки здесь, но учитывая:Проблемы с вложенными Лямбдами

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

Это один очевидный способ сравнения элементов в обр с теми, в 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 \ включить \ xutility (3186): ошибка C2678 : binary '==': оператор не найден, который принимает левый операнд типа 'int' (или нет приемлемого преобразования)

Что мне не хватает?

ответ

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 и тип ОИТ rators являются независимыми.Однако, при осуществлении std::find, должно быть сравнение, как:

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

И в этот момент, вы сравниваете в int (тип выражения *first) с лямбда (тип value) точнее: с закрытием типа. Это плохо сформировано (к счастью), поскольку нет конверсии из лямбда в int, и нет оператора сравнения, объявленного здесь применимым.

+0

Спасибо! Это был глупый контроль с моей стороны. – ForeverLearning

Смежные вопросы