3

Consider this -

#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>
#include <list>

int main()
{
  typedef std::list<int> L;
  L l(5);
  typedef L::const_iterator CI;
  typedef L::iterator I;
  CI cb = l.begin(), ce = l.end();
  I b = l.begin();
  std::transform(cb, --ce, ++b, std::bind2nd(std::plus<CI::value_type>(), 1));
  std::copy(l.begin(), l.end(), std::ostream_iterator<CI::value_type>(std::cout\
));
  std::cout<<std::endl;
  return 0;
}

Acccording to me its output should be 01111 as transform will iterate from first to "second last" element of list add 1 to each element and overwrite from "2nd" to "last" element.

But to my surprise output is 01234

What am I missing ? I read the documentation of transform on cppreference

2 Answers2

3

This is because your are storing the result of each individual transformation into the next element of the source container, so the next input of the transform function will be the output of the previous transform (because of how you defined the input and output ranges).

In other words, the transform() algorithm will process the first element of your container (0), add 1 to it, and store the result (1) as the second element of that same container. Then, it will process the second element, which is now 1; it will add 1 to it, and store the result (2) as the third element of the container. And so on until you get to the last iteration.

If you want to get the output 01111, you should either store the result of the transform into a diffferent container (live example):

std::vector<int> out(l.size());
std::transform(cb, --ce, ++out.begin(), 
//                       ^^^^^^^^^^^^^
    std::bind2nd(std::plus<CI::value_type>(), 1));

Or use a different iteration strategy, as suggested by DyP in the comments (live example):

 std::transform(++cb, ce, ++b, std::bind2nd(std::plus<CI::value_type>(), 1));
Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Wouldn't it suffice to iterate from ++cb to ce, output at ++b? Like `transform(++cb, ce, ++b, ...)` – dyp Jun 26 '13 at 13:45
  • @Andy: thanks for clarifying, I actually thought transform starts writing after performing operation on whole range but i was wrong – Abhishek Dixit Jun 26 '13 at 14:18
3

Since you are starting to add elements into the same container at ++b, there is an off by one offset, which means that you insert element i plus 1 into position i+1. So you are accummulating the sum as you move along. Assuming transform processes the elements sequentially, this is what the first three iterations will do:

0 0 0 0 0

Add 1 to position 0, put it in position 1

0 1 0 0 0

Add 1 to position 1, put it in position 2

0 1 2 0 0

Add 1 to position 2, put it in position 3

0 1 2 3 0

juanchopanza
  • 223,364
  • 34
  • 402
  • 480