dependent name is not a type 1 prefix with 'typename' to indicate a type

I am having trouble compiling the classes below.  I tried adding the typename to the SList declaration but it didn't fix the problem.  

the full error output for this has quite a few errors
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : warning C4346: 'SList<T>::Iterator' : dependent name is not a type
1>        prefix with 'typename' to indicate a type
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : error C2146: syntax error : missing ')' before identifier 'i'
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : error C2182: 'AddAfter' : illegal use of type 'void'
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : error C2470: 'SList<T>::AddAfter' : looks like a function definition, but there is no parameter list; skipping apparent body
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : error C2072: 'SList<T>::AddAfter' : initialization of a function
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(135) : error C2059: syntax error : ')'
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(139) : error C2065: 'T' : undeclared identifier
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(139) : error C2065: 'T' : undeclared identifier
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(139) : error C2143: syntax error : missing ';' before '{'
1>c:\users\mzazzali\documents\visual studio 2008\project\slist.h(139) : error C2447: '{' : missing function header (old-style formal list?)
1>Build log was saved at "file://c:\Users\mzazzali\Documents\Visual Studio 2008\Project\Debug\BuildLog.htm"

Thanks for any help
// file name: SList.h
#ifndef SLIST_H
//SList.h file
#define SLIST_H
#include <assert.h>
//template <class T> class SList;
template <class T> class SList {
public: class Iterator;
		friend class Iterator;
protected:
	struct Node {
		T data;
		Node *next;
		Node() {next = 0;}
		Node(const T& a, Node *p = 0) {data = a; next = p;}
	};
	Node *head, *tail;
public:
	SList() {head = tail = 0;}
	SList(const SList &aSList);
	const SList& operator=(const SList<T> &aSList);
	~SList() { SetToEmpty(); }
	// add item as first item
	void AddFirst(const T& a);
	// remove first item
	void RemoveFirst();
	// add item as last item
	void AddLast(const T& a);
	bool IsEmpty() const;
	// show first item
	const T& ShowFirst() const;
	// remove all items from list
	void SetToEmpty();
	// add item following the position pointed by iterator
	void AddAfter(Iterator i, const T& item);
	// remove item following the position pointed by iterator
	void RemoveAfter(Iterator i);
	class Iterator {
		friend SList;
 
		private:
			Node *nodePointer;
			// construct an iterator and set it to a given node
			Iterator(const Node *setPtr) {nodePointer = const_cast<Node *> ( setPtr ); }
		public:
			//default constructor
			Iterator() : nodePointer( 0 ) {}
			// return reference of the item pointed by Iterator
			T& operator*() const {
			assert( nodePointer != 0 );
			return (*nodePointer).data; 
		}
		// point to the next position (prefix)
		Iterator& operator++() {
			assert( nodePointer != 0 );
			nodePointer = nodePointer->next;
			return *this; 
		}
		// point to the next position (postfix)
		Iterator operator++(int) {
			assert( nodePointer != 0 );
			Iterator retval(*this);
			nodePointer = nodePointer->next;
			return retval; 
		}
		// return true if the two iterators point to the same node
		bool operator==(const Iterator &i) const {return nodePointer == i.nodePointer; }
		// return true if the two iterators do not point to the same node
		bool operator!=(const Iterator &i) const {return nodePointer != i.nodePointer; }
	}; // end class Iterator
	// return iterator set to first node of the list
	Iterator Begin() {
		Iterator ret_Iter(head);
		return ret_Iter;
	}
	// return iterator set to end of the list
	Iterator End() {
		Iterator ret_Iter(0);
		return ret_Iter;
	}
}; 
 
// end class SList/*** IMPLEMENTATION OF LIST MEMBER FUNCTIONS ***/
template <class T> SList<T>::SList(const SList<T> &aSList) {
	head = tail = 0;
	Node *cur = aSList.head;
	while( cur ) {
		AddLast(cur->data);
		cur = cur->next; 
	}
}
template <class T> const SList<T>& SList<T>::operator=(const SList<T> &aSList) {
	if ( this != &aSList) {
		SetToEmpty();
		Node *cur = aSList.head;
		while( cur ) {
			AddLast(cur->data);
			cur = cur->next;
		}
	}
	return *this; 
}
template <class T> void SList<T>::AddFirst(const T& a) {
	if (head == 0)
		head = tail = new Node(a);
	else
		head = new Node(a, head); 
}
template <class T> void SList<T>::RemoveFirst() {
	assert(!IsEmpty());
	Node *tmp = head;
	head = head->next;
	delete tmp;
	if (head == 0) tail = 0; 
}
template <class T> void SList<T>::AddLast(const T& a) {
	if (head == 0){
		head = tail = new Node(a);
	}else {
		tail->next = new Node(a);
		tail = tail->next; 
	}
}
template <class T> bool SList<T>::IsEmpty() const {
	return (head == 0); 
}
template <class T> const T& SList<T>::ShowFirst() const {
		assert(!IsEmpty());
	return (head->data); 
}
template <class T> void SList<T>::SetToEmpty() {
	while(!IsEmpty())
		RemoveFirst(); 
}
 
template <class T> void SList<T>::AddAfter(SList<T>::Iterator i, const T& item) {
	assert (i.nodePointer != 0);
	i.nodePointer->next = new Node(item, i.nodePointer->next); 
}
template <class T> void SList<T>::RemoveAfter(SList<T>::Iterator i) {
	assert (i.nodePointer != 0 && i.nodePointer->next !=0);
	Node *save = i.nodePointer->next;
	i.nodePointer->next = i.nodePointer->next->next;
	delete save;
}
// End of SList class functions implementation
#endif
 
//MyString.h
 
// file name: MyString.h
// 1. preprocessor commands to guard against
// muliple inclusions of the file MyString.h
#ifndef __MYSTRING_H__
#define __MYSTRING_H__
// 2. include file for assertions
#include <assert.h>
#include <fstream>
using namespace std;
// 3. String class interface begins
class String {
public:
	String();
	String( const char *s);
	String( const String &s);
	~String();
	const String& operator=( const String &rhsObject );
	char& operator[]( int index);
	char operator[]( int index) const;
	int Length() const;
	friend bool operator==(const String &lhsObject, const String &rhsObject);
	friend bool operator<(const String &lhsObject, const String &rhsObject);
	friend bool operator>(const String &lhsObject, const String &rhsObject);
	friend bool operator<=(const String &lhsObject, const String &rhsObject);
	friend bool operator>=(const String &lhsObject, const String &rhsObject);
	friend bool operator!=(const String &lhsObject, const String &rhsObject);
	friend String operator+(const String &lhs, const String &rhs);
	const char* C_StyleString() const;
	friend ostream& operator<<( ostream &out, const String &obj);
private:
	//18. rep implements the String object as a dynamic array
	char *rep;
	//19. len keeps track of the length of *this
	int len;
	//20. End of the class interface
};
//21. End of the preprocessor command
// Default constructor
String::String() {
	rep = new char[1];
	rep[0] = '\0';
	len = 0;
}
// Constructor. Converts a char* object to a String object
String::String( const char *s) {
	len=0;
	const char *tmp = s;
	while (*tmp) {
		++len;
		++tmp;
	}
	// so now len is the same as the length of *s
	rep = new char [len + 1] ; // need room for trailing 0
	for (int i = 0; i <= len; ++i)
		rep[i] = s[i];
}
// Copy constructor.
String::String( const String &obj) {
	len=0;
	char *tmp = obj.rep;
		while (*tmp) {
			++len;
			++tmp;
		}
		// so now len is the same as the length of obj.rep
		rep = new char [len + 1] ;
		for (int i = 0; i <= len; ++i)
			rep[i] = obj.rep[i];
}
// Destructor
String::~String() {
	delete [] rep;
	len = 0;
}
// Assignment operator
const String& String::operator=( const String &rhs) {
	if (this != &rhs) {
		len=0;
		char *tmp = rhs.rep;
		while (*tmp) {
			++len;
			++tmp;
		}
		// so now len is the same as the length of obj.rep
		delete [] rep;
		rep = new char [len + 1] ;
		for (int i = 0; i <= len; ++i)
			rep[i] = rhs.rep[i];
	}
	return *this;
}
// Mutator operator[]
char& String::operator[]( int index) {
	// chech whether the index is within bounds
	assert(index <len && index >= 0);
	return rep[index];
}
// Accessor operator[]
char String::operator[]( int index) const {
		// chech whether the index is within bounds
		assert(index <len && index >= 0);
	return rep[index];
}
// Get the length (number of characters) of a String object
int String::Length() const {
	return len;
}
// Friend functions for == comparison
bool operator==(const String &lhs, const String &rhs) {
	if (lhs.Length() == 0) {
		if (rhs.Length() == 0)
			return true;
		else
			return false;
	}
	else {
		int shorter = lhs.Length();
		if (rhs.Length() > shorter)
			shorter = rhs.Length();
		for (int i = 0; i < shorter; i++) {
			if (lhs.rep[i] == rhs.rep[i])
				continue;
			else
				return false;
		}
		if (lhs.Length() == rhs.Length())
			return true;
		else
			return false;
	}
}// end of function operator==
// Friend functions for < comparison
bool operator<(const String &lhs, const String &rhs) {
	if (lhs.Length() == 0) {
		if (rhs.Length() == 0)
			return false;
		else
			return true;
	}
	else {
		int shorter = lhs.Length();
		if (rhs.Length() > shorter)
			shorter = rhs.Length();
		for (int i = 0; i < shorter; i++) {
			if (lhs.rep[i] == rhs.rep[i])
				continue;
			else if (lhs.rep[i] < rhs.rep[i])
				return true;
			else //(lhs.rep[i] > rhs.rep[i])
				return false;
		}
		if (lhs.Length() == rhs.Length())
			return false;
		else if (lhs.Length() < rhs.Length())
			return true;
		else
			return false;
	}
}// end of function operator<
/****************************************************************
The operator== and operator< can be easily implemented if we include
the C++ standard header file string.h which has the following string
comparing function
int strcmp(const char *left, const char *right);
The strcmp returns integers values as follows:
if left < right it returns value < 0
if left > right it returns value > 0
if left == right it returns value = 0
So we can code == and < operators using this function as follows:
bool operator<(const String &lhs, const String &rhs) {
return (strcmp( lhs.rep, rhs.rep) == 0);
}
bool operator<(const String &lhs, const String &rhs) {
return (strcmp( lhs.rep, rhs.rep) < 0);
}
********************************************************************/
// Friend functions for > comparison
bool operator>(const String &lhs, const String &rhs) {
	return (rhs < lhs);
}
// Friend functions for <= comparison
bool operator<=(const String &lhs, const String &rhs) {
	return !(rhs < lhs);
}
// Friend functions for >= comparison
bool operator>=(const String &lhs, const String &rhs) {
	return !(lhs < rhs);
}
// Friend functions for != comparison
bool operator!=(const String &lhs, const String &rhs) {
	return !(lhs == rhs);
}
// Friend function for string concatination
String operator+(const String &lhs, const String &rhs) {
	int strLength = lhs.len + rhs.len +1;
	char *tmpStr = new char[strLength];
	int i;
	for (i = 0; i < lhs.len; ++i)
		tmpStr[i] = lhs.rep[i];
	for (i = 0; i <= rhs.len; ++i)
		tmpStr[lhs.len + i] = rhs.rep[i];
	String retStr(tmpStr);
	delete [] tmpStr;
	return retStr;
}
// Return C style character string
const char* String::C_StyleString() const {
	return rep;
}
// Friend function for output
ostream& operator<<( ostream &out, const String &obj) {
	return out << obj.C_StyleString();
}
#endif
 
//main.cpp file
#include <fstream>
#include <iostream>
#include "MyString.h"
#include "SList.h"
 
void main () {
    ofstream output("test.out", ios::out);
	SList<String> list1;
 
	output.close();
}

Open in new window

LVL 2
ethnarchAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

evilrixSenior Software Engineer (Avast)Commented:
Lines like this...

template <class T> void SList<T>::RemoveAfter(SList<T>::Iterator i) {

Where iterator is a type that is dependent on the template parameter type need to be written like this...

template <class T> void SList<T>::RemoveAfter(typename SList<T>::Iterator i) {

or like this

template <class T> void SList<T>::RemoveAfter(Iterator i) {
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
evilrixSenior Software Engineer (Avast)Commented:
http://womble.decadentplace.org.uk/c++/template-faq.html#type-syntax-error

The code below should now compile.
// file name: SList.h
#ifndef SLIST_H
//SList.h file
#define SLIST_H
#include <assert.h>
//template <class T> class SList;
template <class T> class SList {
public: class Iterator;
		friend class Iterator;
protected:
	struct Node {
		T data;
		Node *next;
		Node() {next = 0;}
		Node(const T& a, Node *p = 0) {data = a; next = p;}
	};
	Node *head, *tail;
public:
	SList() {head = tail = 0;}
	SList(const SList &aSList);
	const SList& operator=(const SList<T> &aSList);
	~SList() { SetToEmpty(); }
	// add item as first item
	void AddFirst(const T& a);
	// remove first item
	void RemoveFirst();
	// add item as last item
	void AddLast(const T& a);
	bool IsEmpty() const;
	// show first item
	const T& ShowFirst() const;
	// remove all items from list
	void SetToEmpty();
	// add item following the position pointed by iterator
	void AddAfter(Iterator i, const T& item);
	// remove item following the position pointed by iterator
	void RemoveAfter(Iterator i);
	class Iterator {
		friend SList;
 
		private:
			Node *nodePointer;
			// construct an iterator and set it to a given node
			Iterator(const Node *setPtr) {nodePointer = const_cast<Node *> ( setPtr ); }
		public:
			//default constructor
			Iterator() : nodePointer( 0 ) {}
			// return reference of the item pointed by Iterator
			T& operator*() const {
			assert( nodePointer != 0 );
			return (*nodePointer).data; 
		}
		// point to the next position (prefix)
		Iterator& operator++() {
			assert( nodePointer != 0 );
			nodePointer = nodePointer->next;
			return *this; 
		}
		// point to the next position (postfix)
		Iterator operator++(int) {
			assert( nodePointer != 0 );
			Iterator retval(*this);
			nodePointer = nodePointer->next;
			return retval; 
		}
		// return true if the two iterators point to the same node
		bool operator==(const Iterator &i) const {return nodePointer == i.nodePointer; }
		// return true if the two iterators do not point to the same node
		bool operator!=(const Iterator &i) const {return nodePointer != i.nodePointer; }
	}; // end class Iterator
	// return iterator set to first node of the list
	Iterator Begin() {
		Iterator ret_Iter(head);
		return ret_Iter;
	}
	// return iterator set to end of the list
	Iterator End() {
		Iterator ret_Iter(0);
		return ret_Iter;
	}
}; 
 
// end class SList/*** IMPLEMENTATION OF LIST MEMBER FUNCTIONS ***/
template <class T> SList<T>::SList(const SList<T> &aSList) {
	head = tail = 0;
	Node *cur = aSList.head;
	while( cur ) {
		AddLast(cur->data);
		cur = cur->next; 
	}
}
template <class T> const SList<T>& SList<T>::operator=(const SList<T> &aSList) {
	if ( this != &aSList) {
		SetToEmpty();
		Node *cur = aSList.head;
		while( cur ) {
			AddLast(cur->data);
			cur = cur->next;
		}
	}
	return *this; 
}
template <class T> void SList<T>::AddFirst(const T& a) {
	if (head == 0)
		head = tail = new Node(a);
	else
		head = new Node(a, head); 
}
template <class T> void SList<T>::RemoveFirst() {
	assert(!IsEmpty());
	Node *tmp = head;
	head = head->next;
	delete tmp;
	if (head == 0) tail = 0; 
}
template <class T> void SList<T>::AddLast(const T& a) {
	if (head == 0){
		head = tail = new Node(a);
	}else {
		tail->next = new Node(a);
		tail = tail->next; 
	}
}
template <class T> bool SList<T>::IsEmpty() const {
	return (head == 0); 
}
template <class T> const T& SList<T>::ShowFirst() const {
		assert(!IsEmpty());
	return (head->data); 
}
template <class T> void SList<T>::SetToEmpty() {
	while(!IsEmpty())
		RemoveFirst(); 
}
 
//template <class T> void SList<T>::AddAfter(SList<T>::Iterator i, const T& item) {
template <class T> void SList<T>::AddAfter(Iterator i, const T& item) {
	assert (i.nodePointer != 0);
	i.nodePointer->next = new Node(item, i.nodePointer->next); 
}
//template <class T> void SList<T>::RemoveAfter(SList<T>::Iterator i) {
template <class T> void SList<T>::RemoveAfter(Iterator i) {
	assert (i.nodePointer != 0 && i.nodePointer->next !=0);
	Node *save = i.nodePointer->next;
	i.nodePointer->next = i.nodePointer->next->next;
	delete save;
}
// End of SList class functions implementation
#endif
 
//MyString.h
 
// file name: MyString.h
// 1. preprocessor commands to guard against
// muliple inclusions of the file MyString.h
#ifndef __MYSTRING_H__
#define __MYSTRING_H__
// 2. include file for assertions
#include <assert.h>
#include <fstream>
using namespace std;
// 3. String class interface begins
class String {
public:
	String();
	String( const char *s);
	String( const String &s);
	~String();
	const String& operator=( const String &rhsObject );
	char& operator[]( int index);
	char operator[]( int index) const;
	int Length() const;
	friend bool operator==(const String &lhsObject, const String &rhsObject);
	friend bool operator<(const String &lhsObject, const String &rhsObject);
	friend bool operator>(const String &lhsObject, const String &rhsObject);
	friend bool operator<=(const String &lhsObject, const String &rhsObject);
	friend bool operator>=(const String &lhsObject, const String &rhsObject);
	friend bool operator!=(const String &lhsObject, const String &rhsObject);
	friend String operator+(const String &lhs, const String &rhs);
	const char* C_StyleString() const;
	friend ostream& operator<<( ostream &out, const String &obj);
private:
	//18. rep implements the String object as a dynamic array
	char *rep;
	//19. len keeps track of the length of *this
	int len;
	//20. End of the class interface
};
//21. End of the preprocessor command
// Default constructor
String::String() {
	rep = new char[1];
	rep[0] = '\0';
	len = 0;
}
// Constructor. Converts a char* object to a String object
String::String( const char *s) {
	len=0;
	const char *tmp = s;
	while (*tmp) {
		++len;
		++tmp;
	}
	// so now len is the same as the length of *s
	rep = new char [len + 1] ; // need room for trailing 0
	for (int i = 0; i <= len; ++i)
		rep[i] = s[i];
}
// Copy constructor.
String::String( const String &obj) {
	len=0;
	char *tmp = obj.rep;
		while (*tmp) {
			++len;
			++tmp;
		}
		// so now len is the same as the length of obj.rep
		rep = new char [len + 1] ;
		for (int i = 0; i <= len; ++i)
			rep[i] = obj.rep[i];
}
// Destructor
String::~String() {
	delete [] rep;
	len = 0;
}
// Assignment operator
const String& String::operator=( const String &rhs) {
	if (this != &rhs) {
		len=0;
		char *tmp = rhs.rep;
		while (*tmp) {
			++len;
			++tmp;
		}
		// so now len is the same as the length of obj.rep
		delete [] rep;
		rep = new char [len + 1] ;
		for (int i = 0; i <= len; ++i)
			rep[i] = rhs.rep[i];
	}
	return *this;
}
// Mutator operator[]
char& String::operator[]( int index) {
	// chech whether the index is within bounds
	assert(index <len && index >= 0);
	return rep[index];
}
// Accessor operator[]
char String::operator[]( int index) const {
		// chech whether the index is within bounds
		assert(index <len && index >= 0);
	return rep[index];
}
// Get the length (number of characters) of a String object
int String::Length() const {
	return len;
}
// Friend functions for == comparison
bool operator==(const String &lhs, const String &rhs) {
	if (lhs.Length() == 0) {
		if (rhs.Length() == 0)
			return true;
		else
			return false;
	}
	else {
		int shorter = lhs.Length();
		if (rhs.Length() > shorter)
			shorter = rhs.Length();
		for (int i = 0; i < shorter; i++) {
			if (lhs.rep[i] == rhs.rep[i])
				continue;
			else
				return false;
		}
		if (lhs.Length() == rhs.Length())
			return true;
		else
			return false;
	}
}// end of function operator==
// Friend functions for < comparison
bool operator<(const String &lhs, const String &rhs) {
	if (lhs.Length() == 0) {
		if (rhs.Length() == 0)
			return false;
		else
			return true;
	}
	else {
		int shorter = lhs.Length();
		if (rhs.Length() > shorter)
			shorter = rhs.Length();
		for (int i = 0; i < shorter; i++) {
			if (lhs.rep[i] == rhs.rep[i])
				continue;
			else if (lhs.rep[i] < rhs.rep[i])
				return true;
			else //(lhs.rep[i] > rhs.rep[i])
				return false;
		}
		if (lhs.Length() == rhs.Length())
			return false;
		else if (lhs.Length() < rhs.Length())
			return true;
		else
			return false;
	}
}// end of function operator<
/****************************************************************
The operator== and operator< can be easily implemented if we include
the C++ standard header file string.h which has the following string
comparing function
int strcmp(const char *left, const char *right);
The strcmp returns integers values as follows:
if left < right it returns value < 0
if left > right it returns value > 0
if left == right it returns value = 0
So we can code == and < operators using this function as follows:
bool operator<(const String &lhs, const String &rhs) {
return (strcmp( lhs.rep, rhs.rep) == 0);
}
bool operator<(const String &lhs, const String &rhs) {
return (strcmp( lhs.rep, rhs.rep) < 0);
}
********************************************************************/
// Friend functions for > comparison
bool operator>(const String &lhs, const String &rhs) {
	return (rhs < lhs);
}
// Friend functions for <= comparison
bool operator<=(const String &lhs, const String &rhs) {
	return !(rhs < lhs);
}
// Friend functions for >= comparison
bool operator>=(const String &lhs, const String &rhs) {
	return !(lhs < rhs);
}
// Friend functions for != comparison
bool operator!=(const String &lhs, const String &rhs) {
	return !(lhs == rhs);
}
// Friend function for string concatination
String operator+(const String &lhs, const String &rhs) {
	int strLength = lhs.len + rhs.len +1;
	char *tmpStr = new char[strLength];
	int i;
	for (i = 0; i < lhs.len; ++i)
		tmpStr[i] = lhs.rep[i];
	for (i = 0; i <= rhs.len; ++i)
		tmpStr[lhs.len + i] = rhs.rep[i];
	String retStr(tmpStr);
	delete [] tmpStr;
	return retStr;
}
// Return C style character string
const char* String::C_StyleString() const {
	return rep;
}
// Friend function for output
ostream& operator<<( ostream &out, const String &obj) {
	return out << obj.C_StyleString();
}
#endif
 
//main.cpp file
#include <fstream>
#include <iostream>
//#include "MyString.h"
//#include "SList.h"
 
void main () {
    ofstream output("test.out", ios::out);
	SList<String> list1;
 
	output.close();
}

Open in new window

0
ethnarchAuthor Commented:
That worked, thank you so much.  I tried putting the typename inside the bracket like SList<typename T>, I don't know where I got that from but I must have misunderstood/misread something somewhere.

Thanks for the help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.