Thread: Providing my own simple iterators

  1. #1
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694

    Providing my own simple iterators

    I follow the example in this link. There, it has an int. I want to have a std::vector<double>.

    Here is my attempt
    Code:
    #include <iterator>     // std::iterator, std::input_iterator_tag
    
    class MyIterator : public std::iterator<std::input_iterator_tag, std::vector<double> >
    {
      std::vector<double>* p;
    public:
      MyIterator(std::vector<double>& x) :p(&x) {}
      MyIterator(const MyIterator& mit) : p(mit.p) {}
      MyIterator& operator++() {++p;return *this;}
      MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;}
      bool operator==(const MyIterator& rhs) {return p==rhs.p;}
      bool operator!=(const MyIterator& rhs) {return p!=rhs.p;}
      double& operator*() {return p->at(0);}
    
      // obviously this is wrong
      void operator=(std::vector<double>::iterator& x) { p=&x; }
      std::vector<double>::iterator begin() { return p->begin(); }
      std::vector<double>::iterator end() { return p->end(); }
    };
    What can I do?
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    That is wrong in very many ways.

    What are you trying to do?

    If you just want to use the iterators of a `std::vector<double>', just call `begin/end' storing the result in a `std::vector<double>::iterator'.

    If you want something else, ignore the example; explain the idea.

    [Edit]
    With "explain the idea", I am not asking for you to tell me again that you want to provide your own iterators.

    I want to know what kind of iterator you want to provide. What does iterator do? For what type of collection does the iterator provide navigation? I am interested in that sort of information.
    [/Edit]

    Soma
    Last edited by phantomotap; 04-25-2014 at 04:59 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Ok, here is the idea.
    I have a class Point, which has as a private member an std::vector.
    I want however, to have another class, that will inherit from Point and I want to be able to increment the iterator of the vectors by a constance factor, e.g. 4. I do not however to let vector exposed to that other class.

    Code:
    class A : public Point {
       void foo(Iterator to the point1 a, Iterator to point2 b) { // or any suitable arguments
          a += 4;
          b += 5;
    }
    Of though of using a typedef maybe. But it would be nice to learn something about iterators too.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    1): The `value_type' of the iterator would still be `double'.
    2): The constructor should be provided, by the `begin'/`end' functions implemented within `Point', the iterators returned by the member variable `std::vector<???>' instance--the containers `begin'/`end'.
    3): The provided iterators should be stored by your custom iterator.

    You may then easily implement the functionality of your custom iterator using the interfaces provided by the "composed" iterators.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I don't get the 3rd point.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    You are going to have to contain the iterators to the actual vector in your custom iterator in order to mess with them.

  7. #7
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Can you provide an example or something? :/
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I guess I can do that. I'm gleaning as much from the conversation as I can, but I really feel like I'm guessing.

    Code:
    class PointsIterator : public std::iterator<std::input_iterator_tag, double>
    {
       private:
       std::vector<double>::iterator containerStart;
       
       public:
       PointsIterator (const std::vector<double>& dataSource): containerStart(dataSource.begin())
       {
       }
    
       double operator * ()
       {
          // operations that should occur during access
          return (*containerStart);
       }
    
       PointsIterator& operator ++ ()
       {
          // operations that should occur during update
          containerStart += 4; // possibly? the idea is still rather opaque to me.
          return (*this);
       }
    };
    I would think you would at least need to know that much about your iterator to write it. Then you have to consider copy semantics and such.

    Point would contain the begin() and end() methods, and would have to call the contructor for the iterator.

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Can you provide an example or something?
    O_o

    I rarely provide examples with so little effort.

    If you want more help, show more effort. Take what you've been told with the code provided by whiteflags and post what you code you manage.

    possibly? the idea is still rather opaque to me.
    The idea has two common names depending on ancestry: skip iterators and filtered iterators.

    Technically, a skip iterator is a specific flavor of a filter iterator where the filter is "skip every x elements".

    The idea is often used in combination with some form of packing.

    Code:
    class SAdapterPackingColor
    {
        // ...
    };
    
    class SColor
    {
        // ...
        typedef SAdapterPackingColor RAdapter;
        // ...
        float mRed;
        float mGreen;
        float mBlue;    
        // ...
    };
    
    // ...
    
    float * sLine = new float[sWidth + padding];
    
    // ...
    
    SIteratorSpan<SColor> sPixels(sLine, sWidth + padding, 3);
    
    // ...
    
    *sPixels = SColor(0.0f, 0.0f, 0.0f); // sLine[0] = 0.0f; sLine[1] = 0.0f; sLine[2] = 0.0f;
    ++sPixels;
    *sPixels = SColor(0.0f, 0.0f, 0.0f); // sLine[3] = 0.0f; sLine[4] = 0.0f; sLine[5] = 0.0f;
    Obviously, the idea works "better" with languages that support a more significant form of "duck typing".

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  10. #10
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Here is where I reached:
    Code:
    class A {
    public:
      class PointsIterator : public std::iterator<std::input_iterator_tag, double>
      {
         private:
         std::vector<double>::iterator p;
    
         public:
         PointsIterator (std::vector<double>& dataSource):
           p(dataSource.begin())
         {
         }
    
         PointsIterator(const PointsIterator& mit) : p(mit.p) {}
    
         double operator * ()
         {
            // operations that should occur during access
            return (*p);
         }
    
         PointsIterator& operator++() {++p;return *this;}
         PointsIterator operator++(int) {PointsIterator tmp(*this); operator++(); return tmp;}
         bool operator==(const PointsIterator& rhs) {return p==rhs.p;}
         bool operator!=(const PointsIterator& rhs) {return p!=rhs.p;}
      };
      // no idea what to put here
      //PointsIterator& begin() { return v.begin(); }
      void push(double a) { v.push_back(a); }
      //typedef typename std::vector<double>::iterator it;
    private:
      std::vector<double> v;
    };
    
    int main()
    {
    
      A numbers;
      numbers.push(1);
      numbers.push(2);
      numbers.push(3);
      numbers.push(4);
      numbers.push(5);
    
      A::PointsIterator from(numbers);
      PointsIterator until(numbers);
      for (PointsIterator it=from.begin(); it!=until.end(); it++)
        std::cout << *it << ' ';
      std::cout << '\n';
    
      return 0;
    }
    Errors:
    Code:
    ./main.cpp: In function ‘int main()’:
    ../main.cpp:56:33: error: no matching function for call to ‘A::PointsIterator::PointsIterator(A&)’
    ../main.cpp:56:33: note: candidates are:
    ../main.cpp:25:6: note: A::PointsIterator::PointsIterator(const A::PointsIterator&)
    ../main.cpp:25:6: note:   no known conversion for argument 1 from ‘A’ to ‘const A::PointsIterator&’
    ../main.cpp:20:6: note: A::PointsIterator::PointsIterator(std::vector<double>&)
    ../main.cpp:20:6: note:   no known conversion for argument 1 from ‘A’ to ‘std::vector<double>&’
    ../main.cpp:57:3: error: ‘PointsIterator’ was not declared in this scope
    ../main.cpp:57:18: error: expected ‘;’ before ‘until’
    ../main.cpp:58:23: error: expected ‘;’ before ‘it’
    ../main.cpp:58:40: error: ‘it’ was not declared in this scope
    ../main.cpp:58:44: error: ‘until’ was not declared in this scope
    make: *** [main.o] Error 1
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  11. #11
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Oh Whiteflags I forgot. I do not want the ++ to do +4. Doing a normal ++ is ok.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I have trouble seeing why you need an iterator.

    What is an iterator to point? What are you iterating over? Unless you cannot make a good argument over something in your point that you could naturally expect to iterate over, I would refrain from making an iterator. I cannot see why you need an iterator for a Point. You are iterator what - sub-points?

    If you want a derived class to be able to iterate over a private variable, how about exposing some protected members functions that returns a const iterator to the vector (appropriately named of course)?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I want the later you said (iterate over the private vector of Point class, without exposing the vector). Well, yes I thought of protected too and other ways to do it. But maybe I just wanted to see a little about iterators too. In order to get the job done, I just overloaded an operator inside the class Point.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Do you know how constructors work?

    You are trying too much at one pass for something you don't understand.

    You should start hitting what I explained in post four. Don't worry about the operators and other stuff. Start by getting the construction correct. Again, the class which owns the custom iterator is responsible for providing a `begin'/`end'.

    [Edit]
    The client code should use a compatible iterator interface which you are responsible for providing.

    A compatible example matching the client code you posted:

    Code:
    int main()
    {
        A numbers;
        numbers.push(1);
        numbers.push(2);
        numbers.push(3);
        numbers.push(4);
        numbers.push(5);
        A::PointsIterator from(numbers.begin());
        A::PointsIterator until(numbers.end());
        for(A::PointsIterator it(from); it != until; ++it)
            std::cout << *it << ' ';
        std::cout << '\n';
        return(0);
    }
    [/Edit]

    Soma
    Last edited by phantomotap; 04-26-2014 at 10:20 AM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  15. #15
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    This outputs the numbers, but I had to remove some refernces..What do you think about it?

    Code:
    class A {
    public:
      class PointsIterator : public std::iterator<std::input_iterator_tag, double>
      {
         private:
         std::vector<double>::iterator p;
    
         public:
         PointsIterator (std::vector<double>::iterator dataSource):
           p(dataSource)
         {
         }
    
         PointsIterator(const PointsIterator& mit) : p(mit.p) {}
    
         double operator * ()
         {
            // operations that should occur during access
            return (*p);
         }
    
         PointsIterator& operator++() {++p;return *this;}
         PointsIterator operator++(int) {PointsIterator tmp(*this); operator++(); return tmp;}
         bool operator==(const PointsIterator& rhs) {return p==rhs.p;}
         bool operator!=(const PointsIterator& rhs) {return p!=rhs.p;}
      };
    
      std::vector<double>::iterator begin() {return v.begin();}
      std::vector<double>::iterator end() {return v.end();}
      void push(double a) { v.push_back(a); }
    private:
      std::vector<double> v;
    };
    
    int main()
    {
        A numbers;
        numbers.push(1);
        numbers.push(2);
        numbers.push(3);
        numbers.push(4);
        numbers.push(5);
        A::PointsIterator from(numbers.begin());
        A::PointsIterator until(numbers.end());
        for(A::PointsIterator it(from); it != until; ++it)
            std::cout << *it << ' ';
        std::cout << '\n';
        return(0);
    }
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. a library or API providing direct access to a running PE address space
    By renzokuken01 in forum Windows Programming
    Replies: 9
    Last Post: 05-24-2009, 01:40 PM
  2. Help with C# iterators
    By dudeomanodude in forum C# Programming
    Replies: 1
    Last Post: 04-28-2008, 03:23 AM
  3. Providing access to member variables between classes
    By Tonto in forum C++ Programming
    Replies: 11
    Last Post: 06-19-2006, 01:06 PM
  4. providing a GUI...novice!
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 05-20-2002, 09:05 AM