C++ Streams: Sources and Destinations of Data

Organization

The library and its hierarchy of classes is split in different files:

<ios>, <istream>, <ostream>, <streambuf> and <iosfwd> aren't usually included directly in most C++ programs. They describe the base classes of the hierarchy and are automatically included by other header files of the library that contain derived classes.

Basic Class Templates

The base of the iostream library is the hierarchy of class templates. The class templates provide most of the functionality of the library in a type-independent fashion.

This is a set of class templates, each one having two template parameters: the char type (charT) parameter, that determines the type of elements that are going to be manipulated and the traits parameter, that provides additional characteristics specific for a particular type of elements.

The class templates in this class hierarchy have the same name as their char-type instantiations but with the prefix basic_. For example, the class template which istream is instantiated from is called basic_istream, the one from which fstream is is called basic_fstream, and so on... The only exception is ios_base, which is by itself type-independent, and therefore is not based on a template, but is a regular class.

Standard Objects

As part of the iostream library, the header file <iostream> declares certain objects that are used to perform input and output operations on the standard input and output.

They are divided in two sets: narrow-oriented objects, which are the popular cin, cout, cerr and clog and their wide-oriented counterparts, declared as wcin, wcout, wcerr and wclog.

Types

The iostream classes barely use fundamental types on their member's prototypes. They generally use defined types that depend on the traits used in their instantiation. For the default char and wchar_t instantiations, types streampos, streamoff and streamsize are used to represent positions, offsets and sizes, respectively.

Manipulators

Manipulators are global functions designed to be used together with insertion (<<) and extraction (>>) operators performed on iostream stream objects. They generally modify properties and formatting settings of the streams. endl, hex and scientific are some examples of manipulators.

A Simple Example

Consider the following piece of code:

#include <iostream>

int main() {
  std::cout << "Hello World!";
  return 0;
}

Now, << is called an operator. Specifically, << inserts the message into the object std::cout (the console) and thus is said to be an inserter.

We could write the reverse: something the user types is extracted from the keyboard (into a variable). In most cases, we would need to prompt the user to write something:

#include <iostream>

int main() {
  ...
  std::cout << "Type your name and press ENTER: ";
  std::cin  >> user_name;

  return 0;
}

So far, we have...

std::ios_base

(From https://cplusplus.com/reference/ios/ios_base/)

class ios_base;

Base class for the entire hierarchy of stream classes in the standard input/output library, describing the most basic part of a stream which is common to all stream objects, independently of their character type.

It has no public constructors, and thus no objects of this class can be declared.

Both ios_base and its derived class basic_ios<> define the components of streams that do not depend on whether the stream is an input or an output stream: ios_base describes the members that are independent of the template parameters (i.e. the character type and traits), while basic_ios<> describes the members that do depend on them.

More specifically, the ios_base class maintains the following information of a stream:

field member functions description
format flags flags, setf, unsetf flags is set of internal flags that affect how certain input/output operations are interpreted or generated. (See member type fmtflags.)
field width width Width of the next formatted element to insert.
display precision precision Decimal precision for the next floating-point value inserted.
locale getloc, imbue The locale object used by the function for formatted input/output operations affected by localization properties.
callback stack register_callback Stack of pointers to functions that are called when certain events occur.
extensible arrays iword, pword, xalloc Internal arrays to store objects of type long and void*.

std::ios_base Member Functions for Formatting

flags()
Get/set format flags (public member function). Prototypes: fmtflags flags() const; and fmtflags flags (fmtflags fmtfl);, where ios_base::fmtflags is a bitmask type.
setf()
Set specific format flags (public member function)
unsetf()
Clear specific format flags (public member function)
precision()
Get/Set floating-point decimal precision (public member function)
width()
Get/set field width (public member function)

std::ios_base::width

streamsize width() const;
streamsize width (streamsize wide);

The first form returns the current value of the field width, while the second form also sets a new field width for the stream.

The field width determines the minimum number of characters to be written in some output representations. If the standard width of the representation is shorter than the field width, the representation is padded with fill characters at a point determined by the format flag adjustfield (one of left, right or internal).

The fill character can be retrieved or changed by calling the member function fill.

The format flag adjustfield can be modified by calling the member functions flags or setf, by inserting one of the following manipulators: left, right and internal, or by inserting the parameterized manipulator setiosflags(...).

The field width can also be modified using the parameterized manipulator setw(w).

An Example:

// field width
#include <iostream>     // std::cout, std::left

int main () {
  std::cout << 100 << '\n';
  std::cout.width(10);
  std::cout << 100 << '\n';
  std::cout.fill('x');
  std::cout.width(15);
  std::cout << std::left << 100 << '\n';
  return 0;
}

std::ios_base::fmtflags

(From https://cplusplus.com/ios_base::fmtflags)

std::ios_base::fmtflags is a type for stream format flags. It is used as a parameter and/or return value by the member functions flags(), setf() and unsetf().

The values passed and retrieved by these functions can be any valid combination of the following member constants:

field member constant effect when set
independent flags boolalpha read/write bool elements as alphabetic strings (true and false).
showbase write integral values preceded by their corresponding numeric base prefix.
showpoint write floating-point values including always the decimal point.
showpos write non-negative numerical values preceded by a plus sign (+).
skipws skip leading whitespaces on certain input operations.
unitbuf flush output after each inserting operation.
uppercase write uppercase letters replacing lowercase letters in certain insertion operations.
numerical base (basefield) dec read/write integral values using decimal base format.
hex read/write integral values using hexadecimal base format.
oct read/write integral values using octal base format.
float format (floatfield) fixed write floating point values in fixed-point notation.
scientific write floating-point values in scientific notation.
adjustment (adjustfield) internal the output is padded to the field width by inserting fill characters at a specified internal point.
left the output is padded to the field width appending fill characters at the end.
right the output is padded to the field width by inserting fill characters at the beginning.

Three additional bitmask constants made of the combination of the values of each of the three groups of selective flags can also be used:

flag value equivalent to
adjustfield left | right | internal
basefield dec | oct | hex
floatfield scientific | fixed

The values of these constants can be combined into a single fmtflags value using the OR bitwise operator (|).

These constants are defined as public members in the ios_base class. Therefore, they can be refered to either directly by their name as ios_base members (like ios_base::hex) or by using any of their inherited classes or instantiated objects, like for example ios::left or cout.oct.

These values of type ios_base::fmtflags should not be confused with the manipulators that have the same name but in the global scope, because they are used in different circumstances. The manipulators cannot be used as values for ios_base::fmtflags, as well as these constants shouldn't be used instead of the manipulators. Notice the difference:

ios_base::skipws     // constant value of type ios_base::fmtflags
skipws               // manipulator (global function) 

Notice that several manipulators have the same name as these member constants (but as global functions instead) - see manipulators. The behavior of these manipulators generally corresponds to the same as setting or unsetting them with ios_base::setf or ios_base::unsetf, but they should not be confused! Manipulators are global functions and these constants are member constants. For example, showbase is a manipulator, while ios_base::showbase is a constant value that can be used as parameter with ios_base::setf.

Example:

// using ios_base::fmtflags
#include <iostream>     // std::cout, std::ios_base, std::ios,
                        // std::hex, std::showbase
int main () {

  // using fmtflags as class member constants:
  std::cout.setf (std::ios_base::hex , std::ios_base::basefield);
  std::cout.setf (std::ios_base::showbase);
  std::cout << 100 << '\n';

  // using fmtflags as inherited class member constants:
  std::cout.setf (std::ios::hex , std::ios::basefield);
  std::cout.setf (std::ios::showbase);
  std::cout << 100 << '\n';

  // using fmtflags as object member constants:
  std::cout.setf (std::cout.hex , std::cout.basefield);
  std::cout.setf (std::cout.showbase);
  std::cout << 100 << '\n';

  // using fmtflags as a type:
  std::ios_base::fmtflags ff;
  ff = std::cout.flags();
  ff &= ~std::cout.basefield;   // unset basefield bits
  ff |= std::cout.hex;          // set hex
  ff |= std::cout.showbase;     // set showbase
  std::cout.flags(ff);
  std::cout << 100 << '\n';

  // not using fmtflags, but using manipulators:
  std::cout << std::hex << std::showbase << 100 << '\n';

  return 0;
}

The code shows some different ways of printing the same result, using both the fmtflags member constants and their homonymous manipulators.

std::basic_ios

template <class charT, class traits = char_traits<charT> >
class basic_ios;

std::basic_ios is a template class to instantiate the base classes for all stream classes.

Both this class template and its parent class, ios_base, define the components of streams that do not depend on whether the stream is an input or an output stream. ios_base describes the members that are independent of the template parameters, while this one describes the members that are dependent on the template parameters.

The class template adds to the information kept by its inherited ios_base component, the following:

field member functions description
Formatting fill character fill Character to pad a formatted field up to the field width (width).
State error state rdstate setstate clear

The current error state of the stream.

Individual values may be obtained by calling good, eof, fail and bad.

See member type iostate.

exception mask exceptions

The state flags for which a failure exception is thrown.

See member type iostate.

Other tied stream tie Pointer to output stream that is flushed before each i/o operation on this stream.
stream buffer rdbuf Pointer to the associated basic_streambuf object, which is charge of all input/output operations.

Template Parameters

charT

Character type

Shall be a non-array POD type

Aliased as member type basic_ios::char_type

traits

Character traits class that defines essential properties of the characters used by stream objects (see char_traits)

traits::char_type shall be the same as charT

Aliased as member type basic_ios::traits_type

Flags/Members

fill() and fill(fillchar)

char_type fill() const;
char_type fill (char_type fillch);

The fill character is the character used by output insertion functions to fill spaces when padding results to the field width.

The parametric manipulator setfill(fill_char) can also be used to set the fill character.

Example:

// using the fill character
#include <iostream>     // std::cout

int main () {
  char prev;

  std::cout.width (10);
  std::cout << 40 << '\n';

  prev = std::cout.fill ('x');
  std::cout.width (10);
  std::cout << 40 << '\n';

  std::cout.fill(prev);

  return 0;
}

Stream Iterators: istream_iterator and ostream_iterator

std::istream_iterator*

Istream iterators are input iterators that read successive elements from an input stream (such as cin). They are constructed from a std::basic_istream object, to which they become associated, so that whenever operator++ is used on the iterator, it extracts an element from the stream (using operator>>).

This kind of iterator has a special state as an end-of-stream iterator, which is acquired if an input operations fails (as returned by bool std::basic_ios::fail() const after an operation with the associated stream), and is also the resulting value of a default-constructed object.

Syntax:

template <
  class T,
  class charT=char,
  class traits=char_traits<charT>,
  class Distance = ptrdiff_t>
class istream_iterator;

where T is the type of elements extracted from the stream.


Its member functions are:

(constructor) Construct istream iterator
operator* Dereference iterator
operator-> Dereference iterator
operator++ Increment iterator

An example:

// istream_iterator example
#include <iostream>     // std::cin, std::cout
#include <iterator>     // std::istream_iterator

int main () {
  double value1, value2;
  std::cout << "Please, insert two values: ";

  std::istream_iterator<double> eos;              // end-of-stream iterator
  std::istream_iterator<double> iit (std::cin);   // stdin iterator

  if (iit!=eos) value1=*iit;

  ++iit;
  if (iit!=eos) value2=*iit;

  std::cout << value1 << "*" << value2 << "=" << (value1*value2) << '\n';

  return 0;
}

std::ostream_iterator

Ostream iterators are output iterators that write sequentially to an output stream (such as cout). They are constructed from a basic_ostream object, to which they become associated, so that whenever an assignment operator (=) is used on the ostream_iterator (dereferenced or not) it inserts a new element into the stream.

Optionally, a delimiter can be specified on construction. This delimiter is written to the stream after each element is inserted.

Syntax:

template <class T, class charT=char, class traits=char_traits<charT> >
class ostream_iterator;

where T is the type of elements inserted into the stream.


Its member functions are:

(constructor) Construct ostream iterator
operator* Dereference iterator
operator++ Increment iterator
operator= Assignment operator

An example:

// ostream_iterator example
#include <iostream>     // std::cout
#include <iterator>     // std::ostream_iterator
#include <vector>       // std::vector
#include <algorithm>    // std::copy

int main () {
  std::vector<int> myvector;
  for (int i=1; i<10; ++i) myvector.push_back(i*10);

  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy ( myvector.begin(), myvector.end(), out_it );
  return 0;
}

Output:

10, 20, 30, 40, 50, 60, 70, 80, 90,