Click here to Skip to main content
13,300,331 members (51,115 online)
Click here to Skip to main content
Add your own
alternative version


29 bookmarked
Posted 6 Jan 2005

Program Objects: Reusing and Redirecting C++ Programs

, 6 Jan 2005
Rate this:
Please Sign up or sign in to vote.
By writing programs as objects, it can be easy to reuse programs, and redirect them to one another.


I remember, as a young programmer at university, how impressed I was with the productivity of the UNIX gurus. They would write sophisticated software in just one or two lines of code using strangely named tools like bash and awk. It took a while until I realized that the secret to their productivity was program reuse. Commonly, UNIX programmers wrote programs in a way that made them easily reused, where the primary input was the standard in, and the primary output was the standard out. This kind of program is often called a UNIX filter. The UNIX shells such as bash, and tools like awk, provided various ways for filters to be chained together and piped to and from files.

It has always bothered me that there was no easy way to achieve the same kind of effect from within C++ other than communicating directly with the OS. It seems to make perfect sense that if I have the source code to two C++ programs which behave like UNIX filters, redirecting the output from one to the other should be written as a one liner:

MyProgram1 > MyProgram2;

Using Program Objects

In order to write programs so that they can be reused in other programs, you can write the program as a class derived from the Program class, i.e.:

// helloworld.hpp

#include <iostream>
#include "programs.hpp"

class HelloWorldProgram : public Program {
  virtual void Main() {
    cout << "Hello world!\n" << endl;

The corresponding .cpp file would contain only the following:

// hello_world.cpp

#include "hello_world.hpp"

int main() {
  return 0;

This might not look like much at first glance, but now your program can be used within another program as if it were a UNIX filter. Consider the following programs:

// upper_case.hpp

#include <iostream.hpp>
#include <cctype.hpp>
#include "programs.hpp"

class UpperCaseProgram : public Program {
  virtual void Main() {
    char c;
    while (cin.get(c)) cout.put(toupper(c));

Now we can combine them:

// upper_case_hello_world.hpp

#include "programs.hpp"
#include "upper_case.hpp"
#include "hello_world.hpp"

class UpperCaseHelloWorldProgram : public Program {
  virtual void Main() {
    HelloWorldProgram() > UpperCaseProgram();

Notice that the Program class overloads the greater-than operator (>).

Redirecting to and from Stream

Program objects can also be redirected to and from streams, i.e.:

stringstream s;
HelloWorldProgram() > s;
s > UpperCaseProgram();

Programs and streams can also be chained together in arbitrarily long sequences:

fstream f("c:\\tmp.txt");
stringstream s;
HelloWorldProgram() > f > UpperCaseProgram() > s;

The only caveat is that one stream can't be redirected to another stream.

The Program Class

Here is the code for the Program class:

class Program {
  Program() {
    old_in = cin.rdbuf();
    old_out = cout.rdbuf();
    old_err = cerr.rdbuf();
    old_log = clog.rdbuf();
  ~Program() {
  void Run() {
  void SetStdIn(istream& in) {
  void SetStdOut(ostream& out) {
  void SetStdErr(ostream& err) {
  void SetStdLog(ostream& log) {
  void ResetStreams() {
  virtual void Main() = 0;
  streambuf* old_in;
  streambuf* old_out;
  streambuf* old_err;
  streambuf* old_log;

The Redirection Operator

The greater-than operator (>) is used as the redirection operator. The following overloads are provided:

PipeChain operator>(Program& in, Program& out) {
  return PipeChain(in, out);

PipeChain operator>(iostream& in, Program& out) {
  return PipeChain(in, out);

PipeChain operator>(Program& in, iostream& out) {
  return PipeChain(in, out);

PipeChain& operator>(PipeChain& in, Program& out) {
  return in;

PipeChain& operator>(PipeChain& in, iostream& out) {
  return in;

The only really tricky part of the library is how PipeChain works. A PipeChain is constructed by the first redirection operator in a chain. In other words, for the example a > b > c;, a > b returns a PipeChain, which is then passed by reference to PipeChain& > c;. This allows us to construct arbitrarily long PipeChains. Only when the chain is destroyed are the programs are redirected and then run.

Anyway, the only thing you really need to know about PipeChain is that when you pipe from a program to another, the programs are run sequentially. The first program stores its output in a stringstream, which is then fed as the input to the second program only after the first program is finished running. The reason for this approach is that it is portable to even single threaded environments.


When writing a program to be reused in the manner described, always keep in mind that the standard input and standard output might be redirected. Also, use only C++ streams and not C-style I/O functions. This library is very exciting and useful to me, because I am continually writing small test and demonstration programs for the various libraries I write. Hopefully, it will be helpful for you as well.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Christopher Diggins
Software Developer Autodesk
Canada Canada
This article was written by Christopher Diggins, a computer science nerd who currently works at Autodesk as an SDK specialist.

You may also be interested in...

Comments and Discussions

Generalproblems compiling Pin
thides17-Jan-05 3:43
memberthides17-Jan-05 3:43 
Generalcat filename.pts| recon Pin
Thibaut vinchon11-Jan-05 4:04
memberThibaut vinchon11-Jan-05 4:04 
GeneralRe: cat filename.pts| recon Pin
Edwin G. Castro12-Jan-05 9:52
memberEdwin G. Castro12-Jan-05 9:52 
GeneralConfusion about redirection and piping. Pin
cdiggins7-Jan-05 8:26
membercdiggins7-Jan-05 8:26 
GeneralDon't worry Pin
Arno Nym7-Jan-05 13:33
sussArno Nym7-Jan-05 13:33 
> means 'greater than operator' and | means 'bitwise inclusive or operator'. So, you are wrong with bothSmile | :)
GeneralRe: Don't worry Pin
Dante Shamest7-Jan-05 15:35
memberDante Shamest7-Jan-05 15:35 
GeneralRe: Don't worry Pin
Simon Hofverberg10-Jan-05 23:47
memberSimon Hofverberg10-Jan-05 23:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171207.1 | Last Updated 6 Jan 2005
Article Copyright 2005 by Christopher Diggins
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid