Lecture Notes for CS 509, Advanced Programming II

21 March 2002, More on Iterators


  1. iterator adaptors - insert iterators

    1. the problem: copy(src.begin(), src.end(), dst.begin()); doesn't work - just iterators can't change container size

    2. the solution - insert iterators, behave like iterators, but can change container size

    3. they are template classes

      1. the template parameter is the container type

      2. the constructor argument is the container and possibly an iterator

      3. there are helper functions that make declarations easy

    4. access via #include <iterator>

    5. three inserters - back inserter, front inserter, and general inserter

      1. back inserter - insert elements at container end

        1. class back_insert_iterator<typename T> bi(C)

        2. helper function back_inserter(c)

        3. when assigned to, calls C.push_back(V)

        4. C must support push_back()

      2. front inserter - insert elements at container front

        1. class front_insert_iterator<typename T> fi(C)

        2. helper function front_inserter(c)

        3. when assigned to, calls C.push_front(v)

        4. C must support push_front()

      3. front inserter - insert elements somewhere in the container

        1. class insert_iterator<typename T> ii(c, p)

        2. helper function inserter(c, p)

        3. when assigned to, calls C.insert(p, v)

        4. the inserter points to the new element when done

  2. iterator adaptors - input and output iterators

    1. i-o streams are like sequential containers - a sequence of values

    2. treat i-o streams like containers - iterator access in particular

    3. simplify and unify container i-o

    4. input and output iterators turn i-o streams into iterator accessible containers

    5. they are template classes

      1. the template parameter is the type of the value being read or written

      2. the constructor parameter is the stream involved

      3. helper functions aren't provided

    6. access via #include <iterator>

    7. ostream iterators

      1. class ostream_iterator<T> oi(ostream, delim)

      2. delim is optional, put between successive elements; it has type const char *

        copy(ivec.begin(), ivec.end(), ostream_iterator<int>(cout, " "))
        

      3. * and ++ are no-ops; = does the write

        ostream_iterator<int> osi(cout, " ");
        
        *osi++ = 1;  // write 1 to std-out
        osi = 2;     // write 2 to std-out
        

      4. the operator << must be defined for values of type T

    8. istream iterators

      1. like ostream iterators, but there's the eof problem, and the error problem

      2. the constructor takes the istream to read

        1. this may read the first value too; it may not

          istream_iterator<T> isi(istream);
          

      3. the default constructor creates an eof iterator

        1. the next iterator after an eof or error is the eof iterator

        2. use == against the eof iterator, not .eof().

          istream_iterator<int> isi(is);
          istream_iterator<int> isi_eof();
          while (isi != isi_eof) { /* whatever */ }
          
          std::copy(istream_iterator<int>(cin), istream_iterator<int>(), 
                    back_inserter(ivec));
          

      4. ++ reads the next stream value, returns the next iterator

      5. * returns the most recently read stream value; it doesn't read a value unless it's the first one

      6. == returns true if two iterators are from the same stream and both are either eof or not eof

        1. the stream values have nothing to do with it.

          istream_iterator<int> isi1(cin);
          istream_iterator<int> isi2(cin);
          
          cerr << (isi1 == isi2 ? "" : "not ") << "equal\n"; // prints "equal"
          int i = *isi1++;
          cerr << (isi1 == isi2 ? "" : "not ") << "equal\n"; // prints "equal"
          

      7. the >> operator must be defined for the value being read


This page last modified on 30 March 2002.