Templates, Classes, Structs Problems

Started by
15 comments, last by Zmurf 18 years, 5 months ago
alright heres my exact code in my header file. It was working fine until I wanted to expand it by making it a template class so it can be more versitile.

// Priority List Definition#ifndef H_PRIORITY_LIST#define H_PRIORITY_LIST// Includes#include <iostream>#include <cstdio>#include <cstdlib>#include <math.h>#include <vector>#include <string>#include <iterator>#include <sstream>#include <algorithm>// Namespacesusing namespace std;template <class T> class plist{// Public Members.public:	plist();				// Constructor, returns nothing.	virtual ~plist();		// Deconstructor, returns nothing.	void add(T val, int pri = 0);								// Add a single string.	void addline(string val, bool newOnly = false);				// Add a string with multiple words.	void remove(int pos){m_List.erase(m_List.begin() + pos);}	// Remove string at position pos.	void sort();												// Sorts the list.	void setpri(int pos, int pri){m_List.at(pos).pri = pri;}	// Sets the priority of position pos in the list.	T getf(){return m_List[0].val;}					// Returns the first string.	T getb(){return m_List[m_List.size()].val;}		// Returns the last string.	T get(int pos){return m_List.at(pos).val;}			// Returns the string at position pos.	int size(){return m_List.size();}		// Returns the size of the list.		int find(string val);					// Finds the first instance of str in the list and 											// returns its position.// Private Members.private:	// Structure to hold the list data in a single vector.	template <class U> struct m_ListDec 	{		U val;		int	pri;		bool operator<(const m_ListDec &rhs) const {			return pri < rhs.pri;		}		bool operator>(const m_ListDec &rhs) const {			return pri > rhs.pri;		}	};	vector< m_ListDec<T> > m_List;// Protected Members.protected:};#endifvoid plist<class T>::add(T val, int pri){	m_ListDec<T> temp = {val, pri};	m_List.push_back(temp);}void plist<class T>::addline(string val, bool newOnly){	vector<string> words;    // Split the input string into a vector	istringstream sentance(val);	copy(istream_iterator<string>(sentance), istream_iterator<string>(), back_inserter(words));    // Add the new words to the list.	for(int i = 0; i < (int)(words.size()); ++i){		if (newOnly){			if (find(words.at(i)) != -1)				add(words.at(i), (int)(words.at(i)[0]));		}		else			add(words.at(i), (int)(words.at(i)[0]));	}}void plist<class T>::sort(){	std::sort(m_List.begin(), m_List.end());}int plist<class T>::find(string val){	for (int i = 0; i < (int)(m_List.size()); ++i){		if (m_List.val = val)			return i;	}	return -1;}
If it's possible for us to conceive it, than it must be possible.
Advertisement
Ok, I have problems with posting code here because of html tags, but I was told a way to get around this. Hopefully I'll do this right the first time.


template < class T > class MyClass
{
public:
template < class U > struct MyStruct
{
U val1;
U val2;
};

std::vector < MyStruct < T > > m_Vector;

void addtovector(T v1, T v2);
};

template < class T >
void MyClass < T >::addtovector(T v1, T v2)
{
MyStruct < T > temp = {v1, v2};
m_Vector.push_back(temp);
}

I basically just tried to correct your syntax. I hope this helps.
Much better :-).

Problem #1: You've got the external member function syntax wrong when it's a member of a template class. It should be:

template < typename T >return_type class_name< T >::function_name( ... )


Instead of:

return_type class_name< class T >::function_name( ... )


This affects the declerations:

void plist<class T>::add(T val, int pri){    ...}void plist<class T>::addline(string val, bool newOnly){    ...}void plist<class T>::sort(){    ...}int plist<class T>::find(string val){    ...}


Fixing these by switching them to:

template < typename T >void plist<T>::add(T val, int pri){    ...}template < typename T >void plist<T>::addline(string val, bool newOnly){    ...}template < typename T >void plist<T>::sort(){    ...}template < typename T >int plist<T>::find(string val){    ...}


Allows my compiler to compile that snippet of code just fine. Full redone source bellow:

// Priority List Definition#ifndef H_PRIORITY_LIST#define H_PRIORITY_LIST// Includes#include <iostream>#include <cstdio>#include <cstdlib>#include <math.h>#include <vector>#include <string>#include <iterator>#include <sstream>#include <algorithm>// Namespacesusing namespace std;template <class T> class plist{// Public Members.public:	plist();				// Constructor, returns nothing.	virtual ~plist();		// Deconstructor, returns nothing.	void add(T val, int pri = 0);								// Add a single string.	void addline(string val, bool newOnly = false);				// Add a string with multiple words.	void remove(int pos){m_List.erase(m_List.begin() + pos);}	// Remove string at position pos.	void sort();												// Sorts the list.	void setpri(int pos, int pri){m_List.at(pos).pri = pri;}	// Sets the priority of position pos in the list.	T getf(){return m_List[0].val;}					// Returns the first string.	T getb(){return m_List[m_List.size()].val;}		// Returns the last string.	T get(int pos){return m_List.at(pos).val;}			// Returns the string at position pos.	int size(){return m_List.size();}		// Returns the size of the list.		int find(string val);					// Finds the first instance of str in the list and 											// returns its position.// Private Members.private:	// Structure to hold the list data in a single vector.	template <class U> struct m_ListDec 	{		U val;		int	pri;		bool operator<(const m_ListDec &rhs) const {			return pri < rhs.pri;		}		bool operator>(const m_ListDec &rhs) const {			return pri > rhs.pri;		}	};	vector< m_ListDec<T> > m_List;// Protected Members.protected:};#endiftemplate < typename T >void plist<T>::add(T val, int pri){	m_ListDec<T> temp = {val, pri};	m_List.push_back(temp);}template < typename T >void plist<T>::addline(string val, bool newOnly){	vector<string> words;    // Split the input string into a vector	istringstream sentance(val);	copy(istream_iterator<string>(sentance), istream_iterator<string>(), back_inserter(words));    // Add the new words to the list.	for(int i = 0; i < (int)(words.size()); ++i){		if (newOnly){			if (find(words.at(i)) != -1)				add(words.at(i), (int)(words.at(i)[0]));		}		else			add(words.at(i), (int)(words.at(i)[0]));	}}template < typename T >void plist<T>::sort(){	std::sort(m_List.begin(), m_List.end());}template < typename T >int plist<T>::find(string val){	for (int i = 0; i < (int)(m_List.size()); ++i){		if (m_List.val = val)			return i;	}	return -1;}
I guess I should get another post in before this hurricane takes out the power.


// this is incorrect

MyClass< class T>::addtovector(T v1, T v2)
{
//...........
}

// this is correct

template< class T>
void MyClass< T>::addtovector(T v1, T v2)
{
//............
}

If you define a member function outside your class declaration you need to have template< class T> at the begining of each function. Also it should be MyClass< T>:: not MyClass< class T>:: . I believe this is why you recieved the error you posted earlier.
Thats gets rid of the main errors. Now theres just one left.

It has to do with this line.

template <typename T> int plist<T>::find(string val){	for (int i = 0; i < (int)(m_List.size()); ++i){		if (!m_List.val.compare(val))  // This line is causing problems.			return i;	}	return -1;}


And I'm recieving these errors.

Quote:
ChatBot.obj : error LNK2019: unresolved external symbol "public: __thiscall plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" (??0?$plist@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@QAE@XZ) referenced in function _$E1


Quote:
ChatBot.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::~plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" (??1?$plist@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@UAE@XZ) referenced in function _$E11
If it's possible for us to conceive it, than it must be possible.
ChatBot.obj : error LNK2019: unresolved external symbol "public: __thiscall plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" (??0?$plist@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@QAE@XZ) referenced in function _$E1

ChatBot.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::~plist<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" (??1?$plist@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@UAE@XZ) referenced in function _$E11

BoldedColored red the important bits.

"unresolved external symbol" means it couldn't find the actual implementation of something. This is usually either because you frogot to link a library (which implements that function), or because you frogot to implement that function yourself.

If you skim over the huge expanded template parameter list, you can see you frogot to implement the the default constructor (plist::plist( void )) and the deconstructor (plist::~plist( void )).
works perfectly now, thankyou all very much
If it's possible for us to conceive it, than it must be possible.

This topic is closed to new replies.

Advertisement