Using operators >> and << for push and pop in a C++ stack

By Brian Fitzgerald

The C++ “>>” (extraction operator) and “<<” (insertion operator) are normally used with I/O streams (cin/cout), but you can overload these operators in your own classes and make them do other things. In this case, I implement a stack of integers. “>>” is used for push and “<<” is used for pop. Here is Stk.cpp, containing the Stk class routines:

#include "Stk.h"

// push i onto the stack

Stk& operator >>(Stk& st, int i) {
	st.ints = (int *) realloc(st.ints, (++st.len * sizeof(int)));
	st.ints[st.len - 1] = i;
	return st;
}

// pop i off the stack
Stk& operator <<(Stk& st, int &i) {
	if (st.len == 0) {
		throw "empty stack";
	}
	i = st.ints[--st.len];
	return st;
}

int Stk::size() {
	return len;
}

int Stk::peek() {
	return ints[len - 1];
}
bool Stk::isempty() {
	return len == 0;
}

A few things to notice:

  • The stack is implemented as ints, an array of int.
  • Push resizes the array with a call to realloc.
  • Operators >> and << are not members of class Stk
  • They are implemented as friends.
  • The friend functions have access to private variables ints and len.
  • In >> and <<, the type of the first argument and the return is &Stk.

Here is the header:

#include 

#ifndef STK_H_
#define STK_H_

class Stk {
public:
	int size();
	int peek();
	bool isempty();
	friend Stk& operator >>(Stk& st, int i);
	friend Stk& operator <<(Stk& st, int &i);
private:
	int *ints = NULL;
	int len = 0;
};

#endif /* STK_H_ */

Here is the main program:

#include 
#include "Stk.h"
using namespace std;

int main() {
	cout << "begin" << endl;

	Stk st;
	cout << "push 3: 13, 17, 19" << endl; 	st >> 13 >> 17 >> 19;

	cout << "stack size=" << st.size() << endl;
	cout << "pop the stack" << endl;
	while (!st.isempty()) {
		int n;
		st << n;
		cout << "popped n=" << n << endl;
	}
	cout << "stack size=" << st.size() << endl;

	cout << "push 3: 29, 31, 37" << endl; 	st >> 29 >> 31 >> 37;
	int i, j, k;
	cout << "pop 2" << endl;
	st << i << j;
	cout << "i=" << i << " j=" << j << endl;
	cout << "peek " << st.peek() << endl;
	cout << "stack size=" << st.size() << endl;
	cout << "push 2: 41, 47" << endl; 	st >> 41 >> 47;
	cout << "pop 1" << endl;
	st << k;
	cout << "popped k=" << k << endl;
	cout << "stack size=" << st.size() << endl;
	// int p, q, r;
	// st << p << q << r; // empty stack exception
	cout << "done" << endl;
	return 0;
}

Points to notice:

  • Expression st >> 13 >> 17 >> 19 is evaluated left to right.
  • st >> 13 is evaluated. The result is st, the stack with 13 pushed.
  • Internally, the partially evaluated expression is now st >> 17 >> 19.
  • st >> 17 is evaluated, and so on.

Output:

C:\Users\Brian Fitzgerald\eclipse-workspace\Stk\Debug>Stk.exe
begin
push 3: 13, 17, 19
stack size=3
pop the stack
popped n=19
popped n=17
popped n=13
stack size=0
push 3: 29, 31, 37
pop 2
i=37 j=31
peek 29
stack size=1
push 2: 41, 47
pop 1
popped k=47
stack size=2
done

This is my Saturday project. The purpose was to refresh some skills and to use C++ language features in an interesting way. I saw something similar in one client’s Sybase CT-Library variable binding code. If we’re going to migrate the application to some other database connectivity library, we need to understand how the existing code works, and from there, develop a a migration action plan.

I am a database administrator, not a developer. Any comments or suggestions from anyone in any field are welcome.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s