Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use boost::transform_iterator with a non-const functor

Tags:

c++

boost

I want to use a transform_iterator to make a delta transformation on a range. By delta transformation I mean that r0 should stay the same and the subsequent elements, ri, are mapped to (ri - ri - 1).

My problem is that as far as I can tell a transform_iterator needs a const functor, but my functor needs to remember the previous value. How can I solve this? Should I just write my own iterator?

The reason I want it as an iterator is that in the next step I want to make a range adaptor from it.

EDIT: It seems transform_iterator does allow non-const functors and that it was really my range adaptor that complained about the lack of constness. I'll keep the question open since the discussion about how appropriate it is to use transform_iterator anyway seems interesting.

like image 529
Gurgeh Avatar asked Feb 19 '23 21:02

Gurgeh


1 Answers

I don't think you can have this work completely correctly with boost::transform_iterator. This is a simple implementation that seems like it might work at first, but doesn't really work well:

#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <iostream>

using std::cout;

struct Delta {
  Delta() : prev_value(0) { }

  int operator()(int value) const
  {
    int result = value-prev_value;
    prev_value = value;
    return result;
  }

  mutable int prev_value;
};

int main(int,char**)
{
  typedef std::vector<int> Items;
  typedef boost::transform_iterator<Delta,Items::iterator,int> Iter;

  Items items;
  items.push_back(4);
  items.push_back(3);
  items.push_back(8);
  { // prints 4 -1 5  -- excellent
    Iter i(items.begin(),Delta()), end(items.end(),Delta());
    for (;i!=end;++i) {
      cout << *i << " ";
    }
    cout << "\n";
  } 
  { // prints 4 0 -- crap
    Iter i(items.begin(),Delta());
    cout << *i << " ";
    cout << *i << "\n";
  }
  return 0;
}

To really make this work, you need to know when the iterator is advanced, so I think you'll need your own iterator.

like image 53
Vaughn Cato Avatar answered Mar 04 '23 19:03

Vaughn Cato