The greatest difference between the SGI compiler and linker provided with Irix 6.x and Microsoft's compiler and linker seems to exist in the linker. Where as Irix will see a template's *.C file and remember the implementation, Microsoft will not. See Microsoft's explaination under Section 3.2.2.
So, when working with VC++, the following inclusions and guarding are required (important points are in RED):
// Stack.H
#ifndef __INC__STACK__
#define __INC__STACK__
template <class T>
class Stack
{
public:
Stack(int = 10);
~Stack() { delete [] stackPtr; }
int push(const T&);
int pop(T&); // pop an element off the stack
int isEmpty()const { return top == -1; }
int isFull() const { return top == size - 1; }
private:
int size; // Number of elements on Stack
int top;
T* stackPtr;
};
// WIN32 is defined by the Microsoft Compiler and Linker
// Rest assured UNIX does not define it.
#ifdef WIN32
#include "Stack.C"
#endif
#endif
// End Stack.H
This creates one problem. As the template is instantiated, the *.C file will show up multiple times. So the *.C file will need to be guarded as follows:
// Stack.C
#ifdef WIN32
#pragma once
#endif
//Constructor with the default size 10
template <class T>
Stack<T>::Stack(int s) {
size = s > 0 && s < 1000 ? s : 10;
top = -1; // initialize stack
stackPtr = new T[size];
}
//Push an element onto the Stack.
template <class T>
int Stack<T>::push(const T& item) {
if (!isFull()) {
stackPtr[++top] = item;
return 1; // push successful
}
return 0; // push unsuccessful
}
//Pop an element off the Stack.
template <class T>
int Stack<T>::pop(T& popValue) {
if (!isEmpty()) {
popValue = stackPtr[top--] ;
return 1; // pop successful
}
return 0; // pop unsuccessful
}
// End Stack.C
This workaround satifies CMSC341's separate compilation requirement. Since the *.C file will only be included if WIN32 is defined, UNIX will disreguard the conditional during preprocessing, compilation, and linking. If interested in what the Irix's compiler defines, see here.
#pragma once is the
C++ way of doing the following:
#ifndef __INC__STACK__ #define __INC__STACK__ // ... #endif
The files that CMSC 341 provides you will also require reworking. So, you'll have to download vector.C, vector.H, string.C, string.H, etc. and guard them appropriately.
Also note, the vector.C file contains the following technique: mallocing for 0 elements. A condition exists where vector<Object>::resize will be called with currentSize == 0. This implies that the vector object was created using new with a size of 0. The following was taken from vector.H:
explicit vector( int theSize = 0 ) : currentSize( theSize )
{ objects = new Object[ currentSize ]; }
UNIX does not complain, but the following code will cause Microsoft VC++ to throw an assert in the Debugger when using virtual destructors (delete[] oldArray when the previous array is 0 in size):
template <class Object>
void vector<Object>::resize( int newSize )
{
Object* oldArray = objects;
int numToCopy = newSize < currentSize ? newSize : currentSize;
objects = new Object[ newSize ];
currentSize = newSize;
for( int k = 0; k < numToCopy; k++ )
objects[ k ] = oldArray[ k ];
delete [ ] oldArray;
}
The work around is as follows for a Windows machine:
template <class Object>
void vector<Object>::resize( int newSize )
{
Object* oldArray = objects;
int numToCopy = newSize < currentSize ? newSize : currentSize;
objects = new Object[ newSize ];
// old position of "currentSize = newSize;"
for( int k = 0; k < numToCopy; k++ )
objects[ k ] = oldArray[ k ];
// conditional added
if(currentSize) {
delete [ ] oldArray;
}
// moved after the delete
currentSize = newSize;
}
The reworked code will cause instrumentation to detect a memory leak on a Windows machine (shown below), but its the lesser of two evils.

Oddly enough, the SGI (and HP) STL - and the Microsoft STL- inline everything in their template code. UMBC has chose to use separate compilation. The following workaround should be performed when working with nested classes/structures. Note that the class being used is named Sample, with a nested structure named Nested:
/////////////////////////////////////////////
// Sample.H
// Sample Header File
//
// Your Name Bozo
// 555-xx-1212
// CMSC 341-x
// Spring 2000
// Project x
// who@gl.umbc.edu
//
// Created: 3/2/00 7:37:09 PM
// Current: 3/2/00 7:37:09 PM
/////////////////////////////////////////////
#pragma once
class Sample {
// In case a forward declaration is needed
// A forward declaration would be needed if
// a public function in Sample (public is
// before private) returned a
// Nested object
struct Nested;
public:
// Constructor
Sample( );
// Copy
Sample(const Sample& rhs);
// Assignment
Sample& operator=(const Sample& rhs);
// Destructor
~Sample( );
private:
struct Nested {
// structs are public by default
// Constructor
Nested( )
#ifdef WIN32
{ }
#else
;
#endif
// Copy
Nested(const Nested& arg)
#ifdef WIN32
{ *this = arg; }
#else
;
#endif
// Assignment
Nested& operator=(const Nested& arg)
#ifdef WIN32
{ *this = arg; return(*this); }
#else
;
#endif
// Destructor
~Nested( )
#ifdef WIN32
{ }
#else
;
#endif
private:
// Some private stuff
}; // End Nested
}; // End Sample
#ifdef WIN32
#include "Sample.C"
#endif
// End Sample.H
/////////////////////////////////////////////
// Sample.C
// Sample Implementation File
//
// Your Name Bozo
// 555-xx-1212
// CMSC 341-x
// Spring 2000
// Project x
// who@gl.umbc.edu
//
// Created: 3/2/00 7:37:08 PM
// Current: 3/2/00 7:37:08 PM
/////////////////////////////////////////////
#ifdef WIN32
#pragma once
#endif
#include "Sample.H"
////////////////////////////////
// Constructor
////////////////////////////////
Sample::Sample( ) { }
////////////////////////////////
// Copy
////////////////////////////////
Sample::Sample(const Sample& rhs) { }
////////////////////////////////
// Assignment
////////////////////////////////
Sample& Sample::operator=(const Sample& rhs) {
return(*this);
}
////////////////////////////////
// Destructor
////////////////////////////////
Sample::~Sample( ) { }
////////////////////////////////
////////////////////////////////
// Nested Class is Guarded
// Irix will use the
// following code. Windows
// will use inline code.
////////////////////////////////
////////////////////////////////
#ifndef WIN32
////////////////////////////////
// Constructor
////////////////////////////////
Sample::Nested::Nested( ) { }
////////////////////////////////
// Copy
////////////////////////////////
Sample::Nested::Nested(const Nested& arg) { }
////////////////////////////////
// Assignment
////////////////////////////////
Sample::Nested& Sample::Nested::operator=(const Nested& arg) {
return(*this);
}
////////////////////////////////
// Destructor
////////////////////////////////
Sample::Nested::~Nested( ) { }
#endif
// End Sample.C