Introduction
This article describes how we can pipe functions together as we would program on the command line.
Filters
A filter is a program which takes its input from the standard input stream (std::cin) and places its output to the standard output stream (std::cout). The reason for writing a program as a filter is that it can be used from the OS shell, to redirect its output to a file or device. Filters can also be piped together, which means redirecting the output from one program to the input of the other. This makes programs written as filters highly flexible and hence more reusable.
Functions as Filters
A function often behaves like a filter, taking some input from the standard input and outputting to the standard output. So there is no reason why we can't treat a function like we would treat a filter, and redirect its standard output to the standard input of another.
Example
Let's say we have the following functions, which operate on the cin and cout streams:
void HelloWorld() {
cout << "hello world" << endl;
}
void CountChars() {
string s;
getline(cin, s);
cout << static_cast<int>(s.size()) << endl;
}
By overloading the greater-than operator (>), we can now write a new function, which outputs the number of characters output onto the stream by HelloWorld().
void CountCharsInHelloWorld() {
filter(HelloWorld) > filter(CountChars);
}
The Code
The code to accomplish this functionality is quite simple.
#include <iostream>
#include <sstream>
using namespace std;
typedef void(*procedure)();
class filter {
public:
filter(procedure x) : proc(x) { }
void operator()(istream& in, ostream& out) {
streambuf* inbuf = cin.rdbuf();
streambuf* outbuf = cout.rdbuf();
cin.rdbuf(in.rdbuf());
cout.rdbuf(out.rdbuf());
proc();
cin.rdbuf(inbuf);
cout.rdbuf(outbuf);
}
private:
procedure proc;
};
void operator>(filter f1, filter f2) {
stringstream s;
f1(cin, s);
s.seekg(0);
f2(s, cout);
}
Summary
This is a very simple technique, but it can be used to write our code in a manner which is much easier to reuse. All of those UNIX programmers weren't wrong!