A Generic Ostream Iterator

by Christopher Diggins
November 11, 2005

    Summary
    Ostream iterators are a handy but under-utilized tool for using the STL to output containers and ranges. Here I provide an alternative, which has a more pleasing syntax.

An ostream iterator, allows you to use STL algorithms, such as std::copy to output a container or range to an output stream. A simple example is:

int main() {
  int array[] = { 1, 2, 4, 8, 16, 32, 64 };
  std::copy(array, array + 7, std::ostream_iterator<int>(std::cout, "\n"));
}

The declaration for an ostream_iterator is clunky because you to know the kind of elements it will be reading. You can make the code more readable as follows:

int main() {
  int array[] = { 1, 2, 4, 8, 16, 32, 64 };
  typedef std::ostream_iterator<int> oiter;
  std::copy(array, array + 7, oiter(std::cout, "\n"));
}

This is still more complex than strictly neccessary. The problem is that the ostream_iterator is a template. An alternative implementation would be to make the operator=() member function a template.

#include <iostream>

struct putter {
  putter(const putter& x) : o(x.o), delim(x.delim) { }
  putter(std::ostream& x = std::cout, const char* s = "") : o(x), delim(s) { }
  template<typename T>
  putter& operator=(const T& x) { o << x << delim; return *this; }
  putter& operator*() { return *this; }
  putter& operator++() { return *this; }
  putter& operator++(int) { return *this; }
  mutable std::ostream& o;
  const char* delim;
};

putter put(std::ostream& o = std::cout, const char* delim = "") {
  return putter(o, delim);
}

Now you can output the contents of any iterator pair with less work.

int main() {
  int array[] = { 1, 2, 4, 8, 16, 32, 64 };
  std::copy(array, array + 7, put(std::cout, "\n"));
}

你可能感兴趣的:(Stream)