1

I have an object that contains a vector. I want to iterate over that object, getting hold of the elements in that vector. This is fine as long as I'm only reading. Writing is another story.

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <vector>
using std::vector;

class data_vector {
private:
  vector<float> coefficients;
public:
  data_vector() : coefficients( vector<float>(5,1.) ) {};
  void trace() { cout << coefficients[0] << endl; };

private:
  int seek{0};
public:
  data_vector &begin() { seek = 0; return *this; };
  data_vector &end()   { seek = coefficients.size(); return *this; };
  bool operator!=( const data_vector &test ) const {
    return seek<test.seek; };
  void operator++() { seek++; };
  float &operator*() { return coefficients.at(seek); };
};

int main() {

  data_vector
    outdata;
  outdata.trace();
  for ( float &d : outdata )
    d = 2. ;
  outdata.trace();

  return 0;
}

I thought the loop would alter the object 1. I'm using a reference to the iterator object 2. the dereference function yields a reference, but it doesn't:

clang++ -std=c++17 -o tester test.cxx && ./tester
1
1
Victor Eijkhout
  • 5,088
  • 2
  • 22
  • 23
  • 5
    I imagine the problem is that the range based for loop is making copies of the 'iterator' you've defined. Since the iterator is also the object you're trying to modify you end up modifying a copy of your object, leaving the original unchanged. Giving an object it's own internal iterator is poor design. Make the iterator a separate class. – john May 28 '20 at 20:30
  • 2
    Besides, your operator != is wrongly implemented. – Igor R. May 28 '20 at 20:35
  • 1
    @IgorR. admitted, but fixing that is not going to solve it, right? – Victor Eijkhout May 28 '20 at 20:37
  • @john You're probably right that I'm iterating over a copy. However, I could use more than a six-word hint how to solve this. If I figure out how to make an iterator class, will that still give me this syntax? – Victor Eijkhout May 29 '20 at 13:35
  • 1
    IIRC correctly what gives you the ranged for loop syntax is the `begin` and `end` methods. But it's those methods that should return new iterator objects. Implementing a new iterator class shouldn't be too hard (although no doubt there's some technical details) since all it needs to do is wrap the vector iterator class. In fact you could even reuse vector iterators as the iterators for your class if you wished. – john May 29 '20 at 18:48

0 Answers0