0

I read here and also here and examples on cpluplus.com And I still don't understand how it works

what confuses me at most how lambdas work with _if algorithms like copy_if that they don't reference containers in the body

     std::vector<int> foo = {25,15,5,-5,-15};
         std::vector<int> bar (foo.size());

          // copy only positive numbers:
          auto it = std::copy_if (foo.begin(), foo.end(), bar.begin(), [](int i)
        {return !(i<0);} )

doesn't reference vector object foo in the body. so how it performs the desired action?

Additionally, I don't understand what is the difference beetween capturing a variable and passing as parameter

I also tried my own example:

vector<unsigned long>v2(10);
for(unsigned long i=0;i<v2.size();i++)
    v2[i]=10-i;
v2.erase(remove_if(v1.begin(), v1.end(),[](unsigned long n) { 

    return n%2==1; } ),v2.end());//remove odd numbers

It compiles (MVS 2010 with Intel Composer 14) but produces rubbish and assertion error.

Community
  • 1
  • 1
Andrey Pro
  • 501
  • 1
  • 10
  • 22
  • 1
    It doesn't reference the vector because it is passing it's individual values 1 at a time into your lambda function for you to check. – RamblingMad May 08 '14 at 06:24
  • how it does it. that is exactly unclear for me – Andrey Pro May 08 '14 at 10:25
  • It could do it any way it likes. It could just do a simple `for(size_t n = 0; n < vector.size(); n++)` and pass each indexed element of the vector into your function then change the indexed value if it gets a true value from your defined function – RamblingMad May 08 '14 at 10:28

2 Answers2

0

You're erasing from vector v2 using iterators from container v1. This is expected to.give you crap results - it's undefined behaviour.

sdkljhdf hda
  • 1,387
  • 9
  • 17
0

If you look at std::copy_if source code, you should see how that works.

Essentially what copy_if does is this:

void copy_if(It1 f1, It1 l1, It2 f2, Pred pred) {
  for (; f1 != l1; ++f1) {
    if (pred(*f1)) {
      *f2 = *f1;
      ++f2;
    }
  }
}

It does not know about containers, nor does it have to. The pair of iterators (f1, l1) specify a range where the items are copied from, the iterators contain all the knowledge about how to get to the element. The iterator f2 specifies the starting point of the destination range. If the destination range is not big enough woul will have a buffer overflow bug. The predicate is a function that indicates whether to copy an element or not. It does not have to know anything about the container, it just needs to be able to tell copy_if whether an element being visited should be copied or not.

Difference between capturing a variable and passing as argument should be explained by the following snippets. This lambda

int captured = 42;
auto functor = [captured](int x) { return x%2 == 0; };

essentially means this:

    int captured = 42;
struct Blah
{
    Blah(int c) : captured_(c) { }
    bool operator()(int x) const { return x%2 == 0; }

    int captured_;
} functor(captured);
sdkljhdf hda
  • 1,387
  • 9
  • 17