Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Template problem

Status
Not open for further replies.

grscot

Programmer
Apr 25, 2003
16
GR
Dear all,
The concept behind the code is:

There is an associationlist that holds association pointers. Each association pointer has two pointers, that point to a book

and to a member object respectively.

Now what I'm trying to do is:
To have the association pointer to use its two pointers to point to an array of books(booklist, up to 10 books) and to an

array of members (memberlist, up to 10) respectively.

If you copy and paste the code the program works ok only for books(adding a new book to the booklist(up to 3 for test

purposes) and displaying the books).

If one wants to add a member and display the members, they have to use the function: get_book(); in the file : template<class

Object>
void List<Object>::displayElement(char* type) of the List.cpp, and also to put in comments the

//book1.displayElement(&quot;Books&quot;); of the main.cpp file.

If I don't use the comments in the main.cpp file and use the get_book() function then an error will occur: &quot; 'get_book'

:cannot convert parameter 1 from 'class Book*' to 'class Member*' &quot;

Could someone suggest a solution using a single template function, for displaying members and books?
The code of each file is:

Code:
//Association.h
#ifndef _ASSOCIATION
#define _ASSOCIATION
//#include &quot;Book.h&quot;
//#include &quot;Member.h&quot;

template<class Book,class Member>
class Association
{
	public:
		//Sets up book and member with parameters
		Association(Book* book, Member* member);
		
		//Returns Book
		Book* linked_book(){return this->book;}
		
		//Returns Member
		Member* linked_member(){return this->member;}
		
	private:
		Book* book;
		Member* member;
};
#endif
Code:
//Association.cpp
#ifndef _ASSOCIATIONCPP
#define _ASSOCIATIONCPP
#include &quot;Association.h&quot;

template<class Book,class Member>
Association<Book,Member>::Association(Book* book, Member* member)
{
	this->book=book;
	this->member=member;
}
#endif
Code:
//AssociationList.h
#ifndef _ASSOCIATIONLIST
#define _ASSOCIATIONLIST
#include &quot;Association.h&quot;
//#include &quot;Book.h&quot;
//#include &quot;Member.h&quot;

const int LIST_SIZE=100;

template<class Book,class Member>
class AssociationList
{
public:
	//It initialises all slots in the associationlist array to zero.
	AssociationList();

	/* It searches the associationlist, if book is found then returns 
	   the member that is connected with.*/
	    Member* get_member(Book* book);
	
	/* It searches the associationlist, if member is found then returns
	   the book that is connected with.*/ 
	    Book* get_book(Member* member);

	   template<class R,class P>
	   R* get_member(P* pArg);
	
	/* Checks that book/member not already linked
	   creates association if objects are free to link
	   returns whether or not link was valid */
	bool link(Book* book,Member* member);

	/* Checks that book and member are linked 
	   deletes association if they are linked
	   returns whether or not unlinking was valid */
	bool unlink(Book* book,Member* member);
private:
	Association<Book,Member>* association_list[LIST_SIZE];
};
#endif
Code:
//AssociationList.cpp
#ifndef _ASSOCIATIONLISTCPP
#define _ASSOCIATIONLISTCPP
#include <iostream>
#include &quot;Association.h&quot;
#include &quot;Association.cpp&quot;
#include &quot;AssociationList.h&quot;
#include &quot;Book.h&quot;
#include &quot;Member.h&quot;
using namespace std;

template<class Book,class Member>
AssociationList<Book,Member>::AssociationList()
{
	cout<<&quot;AssociationList constructor called\n&quot;;
	int index;

	for(index=0; index<LIST_SIZE; index++)
		this->association_list[index]=0;
}

/*template<class R,class P>
R* AssociationList<Book,Member>::get_member(P* pArg)
{
	R* member=0;
	bool searching=true;
	int index=0;

	while(searching)
	{
		if (this->association_list[index])
			if (this->association_list[index]->linked_book()==book)
			{
				member=this->association_list[index]->linked_member();
				searching=false;
			}
			else
				index++;
		else
			index++;
		if (searching && (index == LIST_SIZE))
		{
			searching=false;
		}
	}
	return member;
}*/


template<class Book,class Member>
//Member* AssociationList::get_member(Book* book)

Member* AssociationList<Book,Member>::get_member(Book* book)
{
	Member* member=0;
	bool searching=true;
	int index=0;

	while(searching)
	{
		if (this->association_list[index])
			if (this->association_list[index]->linked_book()==book)
			{
				member=this->association_list[index]->linked_member();
				searching=false;
			}
			else
				index++;
		else
			index++;
		if (searching && (index == LIST_SIZE))
		{
			searching=false;
		}
	}
	return member;
}

template<class Book,class Member>
Book* AssociationList<Book,Member>::get_book(Member* member)
{
	Book* book=0;
	bool searching=true;
	int index=0;

	while(searching)
	{
		if (this->association_list[index])
			if (this->association_list[index]->linked_member()==member)
			{
				book=this->association_list[index]->linked_book();
				searching=false;
			}
			else
				index++;
		else
			index++;
		if (searching && (index == LIST_SIZE))
		{
			searching = false;
		}
	}
	return book;
}

template<class Book,class Member>
bool AssociationList<Book,Member>::link(Book* book,Member* member)
{
	bool searching=true;
	bool success=true;
	int index=0;
	int free_slot;

	while(searching)
	{
		if(this->association_list[index])
			if((this->association_list[index]->linked_book()==book ||
				(this->association_list[index]->linked_member()==member)))
		{
			searching=false;
			success=false;
		}
			else
				index++;
		else
		{
			free_slot=index;
			index++;
		}
		if(searching&&(index == LIST_SIZE))
			searching=false;
	}
	if (success)
		this->association_list[free_slot]=new Association(book,member);
	return success;
}

template<class Book,class Member>
bool AssociationList<Book,Member>::unlink(Book* book,Member* member)
{
	bool searching=true;
	bool success=true;
	int index=0;
	int link_slot;

	while(searching)
	{
		if (this->association_list[index])
			if (this->association_list[index]->linked_book()==book &&
				this->association_list[index]->linked_member()==member)
			{
				searching=false;
				link_slot=index;
			}
			else
				index++;
		else
		{
			index++;
		}
		if (searching && (index == LIST_SIZE))
		{
			searching=false;
			success=false;
		}
	}
	if (success)
		delete this->association_list[link_slot];
	return success;
}
#endif
Code:
//Book.cpp
#include<iostream>
#include&quot;Book.h&quot;
#include&quot;Member.h&quot;
using namespace std;

Book::Book()
{
	cout<<&quot;Book constructor called called\n&quot;;
	this->bookDetails=get_string_ver2(&quot;input book title and author separated by a comma and a space character: &quot;);
}

Book::~Book()
{
	if (this->bookDetails)
		delete [] this->bookDetails;
}

void Book::display(Member* borrower)
{
	cout<<&quot;Book title and author are: &quot;<<this->bookDetails<<&quot;.&quot;<<endl;
	if (borrower)
		cout<<&quot;The member's name is: &quot;<<borrower->get_name()<<&quot;.&quot;<<endl;
	else
		cout<<&quot;No member has borrowed a book.&quot;<<endl;
}
Code:
//Book.h
#ifndef _BOOK
#define _BOOK
#include &quot;utility.h&quot;
class Member;//Forward Reference
class Book
{
public:
	//Reads and allocates space for title and author.
	Book();
	
	//Releases the space pointed at by the title and author.
	~Book();
	
	//Returns the book title and author.
	char* get_bookDetails(){return this->bookDetails;}

	//Displays the book title and author and the member who has borrowed the book as applicable.
	void display(Member* borrower);
private:
	Member* borrower;
	char* bookDetails;
};
#endif
Code:
//Member.cpp
#include<iostream>
#include&quot;Book.h&quot;
#include&quot;Member.h&quot;
using namespace std;

Member::Member()
{
	cout<<&quot;Member constructor called\n&quot;;
	this->name=get_string(&quot;Input member's surname and forename respectively, separated by a comma and a space character: 

&quot;);
}

Member::~Member()
{
	if (this->name)
		delete [] this->name;
}

void Member::display(Book* book)
{
	cout<<&quot;Member's name is: &quot;<<this->name<<&quot;.&quot;<<endl;
	if (book)
		cout<<&quot;Book title and author are: &quot;<<book->get_bookDetails()<<&quot;.&quot;<<endl;
	else
		cout<<this->name<<&quot; has not borrowed any book.&quot;<<endl;
}
Code:
//Member.h
#ifndef _MEMBER
#define _MEMBER
#include &quot;utility.h&quot;
class Book;//Forward Reference
class Member
{
public:
	//Reads and allocates space for member's full name.
	Member();
	
	//Releases the space pointed at by name.
	~Member();

	//Returns member's full name.
	char* get_name(){return this->name;}

	//Displays the member's full name and the book borrowed by the member as applicable. 
	void display(Book* book);
private:
	Book* book;
	char* name;
};
#endif
Code:
//List.cpp
#ifndef _LISTCPP
#define _LISTCPP
#include <iostream>
#include &quot;AssociationList.h&quot;
//#include &quot;Book.h&quot;
#include &quot;List.h&quot;
//#include &quot;Member.h&quot;

using namespace std;

template<class Object>
List<Object>::List()
{
	this->num_elements=0;
}

template<class Object>
List<Object>::~List()
{
	for(int element=0; element<this->num_elements; element++)
		delete this->element_list[element];
}

template<class Object>
void List<Object>::addElement(char* type)
{
	if (this->num_elements == MAX_ELEMENTS)
	{
		cout<<&quot;No more room in the &quot;<<type<<&quot; array.\n&quot;;
		cout<<&quot;The maximum number of &quot;<<type<<&quot; is &quot;<<MAX_ELEMENTS<<&quot;.&quot;<<endl;
	}
	else
	{
		this->element_list[num_elements]=new Object;
		(this->num_elements)++;
	}
}

template<class Object>
void List<Object>::displayElement(char* type)
{
	if (num_elements == 0)
		cout<<&quot;No &quot;<<type<<&quot; is found in the &quot;<<type<<&quot; array.\n&quot;;
	else
		for(int element=0; element<this->num_elements; element++)
		{
			cout<<'\n';
			this->element_list[element]->display(association_list.get_member(element_list[element]));
		}
}


template<class Object>
void List<Object>::borrowElement()
{
	cout<<&quot;Borrow book function invoked\n&quot;;
}

template<class Object>
void List<Object>::returnElement()
{
	cout<<&quot;Return book function invoked\n&quot;;
}



#endif
Code:
//List.h
#ifndef _LIST
#define _LIST
#include &quot;AssociationList.h&quot;
#include &quot;Book.h&quot;
#include &quot;Member.h&quot;
const int MAX_ELEMENTS=3;
template<class Object>
class List
{
	public:
			List();
			~List();
			void addElement(char* type);
			void removeElement();
			void displayElement(char* type);
			void borrowElement();
			void returnElement();
	private:
			AssociationList<Book,Member>association_list;
			Object* element_list[MAX_ELEMENTS];
			int num_elements;
};
#endif
Code:
//utility.cpp
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
#define cinFlush cin.seekg(ios::end)

char* get_string (char* prompt)
{
	const int MAX_SIZE=100;
	char string[MAX_SIZE];
	char* out_string;
	char *substring=&quot;, &quot;;
	int position=0;
	bool result=false;
	do
	{
		cout<<prompt; cinFlush;
		//cin>>string;
		//cin.get();
		cin.getline(string,MAX_SIZE);
		if (strstr(string,substring) == NULL)
		{
			cout<<&quot;Invalid Name(substring ', ' not found into the string)&quot;<<endl;
			result=false;
		}
		else
		{
			position=strstr(string,substring) - string;
			if (position == 0)
			{
				cout<<&quot;Invalid Name(substring ', ' found in the beginning of the string)&quot;<<endl;
				result=false;
			}
			else if (toascii(string[position + 1]) == 32 && string[position + 2] == '\0')
			{
				cout<<&quot;Invalid Name(substring ', ' found at the end of the string)&quot;<<endl;
				result=false;
			}
			else
			{
				for(int j=0; j<position; j++)
					if ((toascii(string[j]) >= 0 && toascii(string[j]) <= 64)
						|| (toascii(string[j]) >= 91 && toascii(string[j]) <= 96)
						|| (toascii(string[j]) >= 123 && toascii(string[j]) <= 127))
					{
						cout<<&quot;Invalid character(s) found before the substring ', '&quot;<<endl;
						result=false;
						break;
					}
					else
					{
						for(int m=position + 2; m<strlen(string); m++)
							if ((toascii(string[m]) >= 0 && toascii(string[m]) <= 64)
								|| (toascii(string[m]) >= 91 && toascii(string[m]) <= 96)
								|| (toascii(string[m]) >= 123 && toascii(string[m]) <= 127))
							{
								result=false;
								break;
							}
							else
								result=true;
					}

			}
		}
		}while(!result && !cin.eof());
		out_string=new char [strlen(string)+1];
		if (out_string)
			strcpy(out_string,string);
		return out_string;
}


char* get_string_ver2 (char* prompt)
{
	const int MAX_SIZE=100;
	char string[MAX_SIZE];
	char* out_string;
	char *substring=&quot;, &quot;;//new
	int position=0;//new
	bool result=false;//new
	do//new
	{//new
		cout<<prompt; cinFlush;
		//cin>>string;
		//cin.get();
		cin.getline(string,MAX_SIZE);
		if (strstr(string,substring) == NULL)
		{
			cout<<&quot;Invalid String(substring ', ' not found into the string)&quot;<<endl;
			result=false;
		}
		else
		{
			position=strstr(string,substring) - string;
			if (position == 0)
			{
				//cout<<&quot;Substring found at position: &quot;<<position<<endl;
				cout<<&quot;Invalid String(substring ', ' found in the beginning of the string)&quot;<<endl;
				result=false;
			}
			else if (toascii(string[position + 1]) == 32 && string[position + 2] == '\0')
			{
				//cout<<&quot;Substring found at position: &quot;<<position<<endl;
				cout<<&quot;Invalid String(substring ', ' found at the end of the string)&quot;<<endl;
				result=false;
			}
			else
			{
				for(int z=0;z<position; z++)
					if  (!(( toascii(string[z]) > 64 && toascii(string[z]) < 91 ) 
						|| ( toascii(string[z]) > 96 && toascii(string[z]) < 123)
						|| ( toascii(string[z]) == 32)))
					{
						cout<<&quot;Invalid character(s) found before the substring&quot;<<endl;
						result=false;
						break;
					}
					else
					{
						for(int m=position + 2; m<strlen(string); m++)
							if (!(( toascii(string[z]) > 64 && toascii(string[z]) < 91 ) 
						       || ( toascii(string[z]) > 96 && toascii(string[z]) < 123)
						       || ( toascii(string[z]) == 32)))
							{
								result=false;
								break;
							}
							else
								result=true;
					}

			}
		}
		}while(!result);
		out_string=new char [strlen(string)+1];
		if (out_string)
			strcpy(out_string,string);
		return out_string;
}







void hold_screen()
{
	char ch;

	cout << &quot;hit enter to continue&quot; << endl;
	cin.get(ch);
}

void prompt_to_quit()
{
	char ch;

	cout << &quot;hit enter to quit&quot; << endl;
	cin.get(ch);	
}
Code:
//utility.h
#ifndef _UTILITY
#define _UTILITY
/* prompts for a string, checks for the existence of 
   the substring ', ' and for valid characters before 
   and after the substring and finally dynamically 
   allocates space to store the string, returns the 
   pointer to the allocated storage or 0 if the allocation fails */
char* get_string (char* prompt);

/* prompts for a string, checks for the existence of 
   the substring ', ' and for valid characters before 
   and after the substring and finally dynamically 
   allocates space to store the string, returns the 
   pointer to the allocated storage or 0 if the allocation fails */
char* get_string_ver2(char* prompt);

/* prompts for a carriage return character to hold
   window on display before program continues */
void hold_screen();

/* prompts for a carriage return character to hold
   window on display before program ends */
void prompt_to_quit();

/* prompts for a string up to 100 characters
   and checks whether the string characters are all alphabetical
   returns either true or false. */
//bool validateInput(char *input);

#endif
and finally
//main()
Code:
#include <iostream>
#include &quot;List.cpp&quot;
#include &quot;Association.cpp&quot;
#include &quot;AssociationList.h&quot;
#include &quot;AssociationList.cpp&quot;
#include &quot;Book.h&quot;
#include <conio.h>
#include &quot;Member.h&quot;
#include &quot;utility.h&quot;
#define cinFlush cin.seekg(ios::end)
using namespace std;

void main()
{
	List<Member>member1;
	List<Book>book1;
	char menuChoice;
	do
	{
		cout<<'\n';
		cout<<'\n';
		cout<<&quot;**** Main Menu ****&quot;<<endl;
		cout<<'\n';
		cout<<&quot;1: Add Book        &quot;<<endl;
		cout<<'\n';
		cout<<&quot;2: Remove Book     &quot;<<endl;
		cout<<'\n';
		cout<<&quot;3: Display Books   &quot;<<endl;
		cout<<'\n';
		cout<<&quot;4: Add Member      &quot;<<endl;
		cout<<'\n';
		cout<<&quot;5: Remove Member   &quot;<<endl;
		cout<<'\n';
		cout<<&quot;6: Display Members &quot;<<endl;
		cout<<'\n';
		cout<<&quot;7: Borrow Book     &quot;<<endl;
		cout<<'\n';
		cout<<&quot;8: Return Book     &quot;<<endl;
		cout<<'\n';
		cout<<&quot;0: Quit            &quot;<<endl;
		cout<<endl;
		cout<<&quot;Enter one of the above choices: &quot;;cinFlush;
		cin>>menuChoice;
		switch(menuChoice)
		{
		case '1': cout<<'\n';
                  book1.addElement(&quot;Books&quot;);
			      break;
		case '2': cout<<'\n';
			      
				  break;
		case '3': cout<<'\n';
			      book1.displayElement(&quot;Books&quot;);
				  break;
		case '4': cout<<'\n';
			      //member1.addElement(&quot;Member&quot;);
				  break;
		case '5': cout<<'\n';
			      
				  break;
		case '6': cout<<'\n';
			      //member1.displayElement(&quot;Member&quot;);
				  break;
		case '7': cout<<'\n';
			      //book1.borrowElement();
				  break;
		case '8': cout<<'\n';
			      //book1.returnElement();
				  break;
		default:  cout<<'\n';
			      cout<<&quot;Invalid Selection\n&quot;;
		}
	}while(menuChoice != '0' && !cin.eof());
	prompt_to_quit();
}

What I want to do is to use one function for displaying members and books (to use a template).
What needs to be changed to use only one function for displaying members and books?

Regards,
grscot

 
Why does it have to be a single template function? You could easily make a function template without a definition, then specialize for the two cases, but then you're writing two functions anyway, so there's no point.

You could do some fancy template metaprogramming that makes the Association class a two-tuple with a templated access function that returns each member based on type, but that's a lot of trouble for little benefit, and not something I'd recommend doing if you're having trouble with templates already. Plus it'd be useless for Associations where both members are the same type.

I'd suggest just making it two separate functions.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top