Home > Articles > Programming > C/C++

Combining User-Defined Inserters, Extractors, and Manipulators in C++

📄 Contents

  1. Using Manipulators To Control Object Format
  2. Connecting Algorithms and Containers to Streams
  3. Summary
  • Print
  • + Share This
In part 1 of this series, Cameron and Tracey Hughes covered how to create user-defined extractors and inserters to help facilitate the process of reading, writing, storing, and retrieving user-defined objects. In part 2, they discussed how defining manipulators for user-defined objects helps in the formatting of those objects when inserted into or extracted from streams. In this article, they explore how to use object streaming with the STL containers by combining inserters, extractors, and manipulators with stream iterators.
From the author of

Let's take a look at how to use object streaming with the STL containers by combining inserters, extractors, and manipulators with stream iterators. We'll show how to use manipulators to control the format of objects as they're inserted into or extracted from STL containers. We'll also explore how to use custom ostream, istream, and streambuf classes with the stream iterators and algorithms.

Using Manipulators To Control Object Format

Objects can be streamed to and from virtually any I/O device that can be connected to the computer. In many situations, it's advantageous to move objects directly from a stream to an STL container. Likewise, it's often useful to move objects that are stored in STL containers to an iostream of some type. For instance, if a file contains a collection of objects that need to be sorted, one method of sorting those objects would be to read them into memory, store them in a container, and then sort the container's contents. In this case, it would save some effort if we could stream the objects directly into a sorted container. Or, if we want to save a collection of objects for future processing, it would be convenient to be able to stream the collection directly to a file.

Streaming to and from containers is straightforward for the built-in types, but we would like to be able to stream our own user-defined objects. Further, the supplier of a class must realize that users of that class will expect objects of that type to be compatible with the standard I/O, container, and algorithm facilities in C++. Because streaming is fundamental in object-oriented C++ programming, it's almost a necessity to design your classes and objects with streaming in mind. If your classes define the necessary operators, it will be easy for the user of your objects to stream them to and from STL containers.

For user-defined objects, the streaming process typically requires three steps:

  1. Translation.

  2. Formatting.

  3. Writing/reading the actual I/O device or device buffer.

As we explained in part 1 of this series, insertion is the process of putting objects into the stream. Extraction is the process of removing objects from the stream. During object insertion, the object is translated from its native format to simpler built-in types. The built-in types are then properly formatted for the output device and inserted into the output stream. During extraction, the reverse happens. The object's components are retrieved from the output device, formatted as simple built-in types, and then translated into the object's native format. Figure 1 shows the streaming process for insertion; Figure 2 shows the streaming process for extraction.

Figure 1Figure 1 The streaming process for inserting user-defined objects.

Figure 2Figure 2 The streaming process for extracting user-defined objects.

Notice in the figures that the ostream_iterator and the istream_iterator use the << insertion operator and the >> extraction operator, respectively. These operators manage the streaming process. The implementations of these operators for the user-defined class will take advantage of or set any necessary manipulators and then they will ultimately call the functions that interact with the I/O device. It's important to have this process clear because the stream iterators that connect the iostreams to the STL containers and algorithms require the insertion and extraction operators to be defined for user-defined objects. Further, since the stream iterators work with istream classes, ostream classes, and their descendants, the user can take advantage of any built-in manipulators or user-defined manipulators to format the objects as desired prior to inserting them into or extracting them from the stream.

Table 1 shows where inserters, extractors, and manipulators fit in the streaming process.

Operator/Method

Process

Associated Stream Classes

<<, >>

Translation

basic_istream

basic_ostream

basic_ifstream

basic_ofstream

basic_istrstream

basic_ostrstream

manipulators

setw, setf, hex, fill()

scientific(), etc.

Formatting

ios_base

basic_ios

write, read, put, get

Actual I/O processing

basic_streambuf

basic_filebuf

stringstreambuf


To take advantage of streaming, the supplier or designer has to do a little extra work up front, but the payoff is considerable as the class is used and reused.

  • + Share This
  • 🔖 Save To Your Account