Link List With Templates

hi All

I Have been Searching the Internet For A while Now And could Not Find A Good Answer.

My Question Is Can We Make A Link List Of Which`s node Only Contains One Data Element e.g int float etc etc.... but the link list can contain different node types.... like this where [] is one node

[(int=12) (next->) ] - [(float=45.6) (next->)] - [(char='c') (next=NULL)]

I tried
tempalate <class T>
class node
{
public:
T data;
Node < T > * Next;
};

but this Logic Wont Work ...
Cause Node<float> `s address cant be saved into Node *.or ViseVersa Or anyother type...

i would Prefer a Solution With templates Used


CAn It Be DOne Where am I going Wrong
One way would be to have
1
2
3
4
5
6
template <class Head, class Tail>
class Node{
public:
   Head data;
   Tail* next;
};
The type of your list will then have to be Node<int, Node<float, Node<char, void> > >. I'm sure you can see how that would be a problem.
Another way would be
1
2
3
4
5
class Node{
public:
   void* data;
   Node* next;
};
But now you don't have a way to tell what points to what type.
An improvement would be to add a member std::type_info tp;. Then when inserting elements, you'd pass their typeid and when retrieving you'd use a function
1
2
3
4
5
6
7
template<class T>
bool getData( Node* n, T& result ){
   if( n == 0 || typeid(T) != n->tp ) return false;
   T* ptr = (T*)n->data;
   result = *ptr;
   return true;
}


Note that either way this is hardly ever the right thing to do. If there is some problem you're trying to solve with this, post it here and we'll try to find a better solution.
#include <iostream.h>
#include <typeinfo>
#include <string.h>
#include <windows.h>
#include <stdio.h>


class Node
{
public:

char * c;
int * i;
double * f;

Node * next;

void valuesetter()
{
cout<<" Enter Data the type of Data You Want To Enter "<<endl;
cout<<" 1.Int 2.Float 3.Char : ";

int input;
cin>>input;
cout<<endl;
if(input==1)
{
cout<<" Enter The Data You Want To Put ";
cin>>input;
i=new int;
*i=input;
}

if(input==2)
{
double a;
cout<<" Enter The Data You Want To Put ";
cin>>a;
f=new double;
*f=a;
}
if(input==3)
{
char a;
cout<<" Enter The Data You Want To Put ";
cin>>a;
c=new char;
*c=a;
}
}

void displaydata()
{
if(c!=NULL)
cout<<*c;
if(i!=NULL)
cout<<*i;
if(f!=NULL)
cout<<*f;

}



Node()
{
next=NULL;
c=NULL;
i=NULL;
f=NULL;
}
};


class List
{
public:
Node * first;
Node * last;

List()
{
first=last=NULL;
}

void create()
{
Node *temp=NULL;

temp=new Node;
temp->valuesetter();

if(first==NULL)
{
first=temp;
last=temp;
}
else
{
last->next=temp;
last=temp;
}

cout<<" Enter More Y/N";
char c;
cin>>c;
if(c=='y')
create();
else
return;

}

void print()
{
Node *temp=NULL;
temp=first;

while(temp!=NULL)
{
temp->displaydata();
cout<<" ";
temp=temp->next;
}

}
};


void main()
{
List a;
a.create();

cout<<endl<<endl;

a.print();
}

THis What I Am Trying To Do With A Better Logic i.e templates
Last edited on
Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct AbstractNode{
   AbstractNode* next;
   virtual void read() = 0;
   virtual void write() = 0;
};

template<typename T>
struct Node : AbstractNode {
   T data;
   void read(){
      std::cin >> data;
   }
   void write(){
      std::cout << data;
   }
};

class List{
   ...
   void create(){
      ...
      std::cout << "do you want a 1.char or 2.int ?";
      int choice;
      std::cin >> choice;
      if (choice==1) temp = new Node<char>;
      else temp = new Node<int>;
      temp -> read();
      ...
   }
   ...
};
...
Of course a templated linked list is possible. Here's a basic outline of one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template< typename T >
struct node {
    T data;
    node<T> * next;
};

template< typename T >
class List {
    public:
        List();
        ~List();
    private:
        node<T> * first;
        node<T> * last;

        int size;
};


And then each function and constructor within the class would need to be templated.

1
2
3
4
template< typename T >
List<T>::List() {
    // Constructor
}


The only problem I've run into is that if you try to write the constructor/function definitions in a separate CPP file, the template will cause problems unless you include lines like this at the bottom:

1
2
3
template class List<int>;
template class List<double>;
template class List<float>;


The only problem with that is that you will only be able to create a List object of those types, limiting the types of objects you can store to what you template at the bottom of your CPP file.

The only solution I've found to this is to put the class function/constructor definitions within the header file with the class declaration. It is also a good idea to enclose everything in a namespace.
@packetpirate: Your templated list is for single-type lists. Once 'T' is assigned a true type 'Tx', *first and *last will also be defined as Node<Tx>, which is not the point. hamsterman's solution avoids this by providing another level of abstraction.
@hamsterman

I think U did not read Question Properly Cause Node<float> `s address cant be saved into Node *.or ViseVersa Or anyother type...


according to the code u submitted What Will be type of the variable temp.

temp will be AbstractNode*. Sorry I didn't make that clear.
Thank You Guys i was Finally Able To Do It This Way

#include <iostream>
using namespace std;
#include <conio.h>

template <class T>
class Node
{
public:
T data;
void *next;
char *type;

Node()
{
type=NULL;
next=NULL;
type=new char[10];
}
};

class Link
{


public:
void *first;
void *last;
char *type;


Link()
{
first=NULL;
type=new char [10];
strcpy(type,"none");
}

void makelist()
{
void *temp=first;
int choice;
cout<<"Which Type of Data You Want To Enter "<<endl;
cout<<" 1.Int 2.float 3.char : ";
cin>>choice;
if(choice==1)
{

if(temp==NULL)
{
Node<int> *temp2 = new Node<int>;
strcpy(type,"int");
cout<<"Enter int Data : ";
cin>>temp2->data;
first=temp2;
last=temp2;
}

else
{
Node<int>* temp2=((Node<int>*)last);
strcpy(temp2->type,"int");

Node<int> *temp3 = new Node<int>;
cout<<"Enter int Data : ";
cin>>temp3->data;

temp2->next=temp3;
last=temp3;
}


}
if(choice==2)
{
if(temp==NULL)
{
Node<float> *temp2 = new Node<float>;
strcpy(type,"float");
cout<<"Enter float Data : ";
cin>>temp2->data;
first=temp2;
last=temp2;
}

else
{
Node<float>* temp2=((Node<float>*)last);
strcpy(temp2->type,"float");

Node<float> *temp3 = new Node<float>;
cout<<"Enter float Data : ";
cin>>temp3->data;

temp2->next=temp3;
last=temp3;
}
}
if(choice==3)
{
if(temp==NULL)
{
Node<char> *temp2 = new Node<char>;
strcpy(type,"char");
cout<<"Enter char Data : ";
cin>>temp2->data;
first=temp2;
last=temp2;
}

else
{
Node<char>* temp2=((Node<char>*)last);
strcpy(temp2->type,"char");

Node<char> *temp3 = new Node<char>;
cout<<"Enter char Data : ";
cin>>temp3->data;

temp2->next=temp3;
last=temp3;
}
}

cout<<" Do You Want To Enter For Data (y/n) ?";
char asd;
cin>>asd;
if(asd=='y' || asd == 'Y')
{
cout<<endl;
makelist();

}
else
return;

}

void display()

{
void * temp=first;
char * x=new char [10];
strcpy(x,type);

while(temp!=NULL)

{
if(strcmp(x,"int")==0)
{
Node<int>* temp2=((Node<int>*)temp);
cout<<" "<<temp2->data;
strcpy(x,temp2->type);
temp=temp2->next;
}
if(strcmp(x,"float")==0)
{
Node<float>* temp2=((Node<float>*)temp);
cout<<" "<<temp2->data;
strcpy(x,temp2->type);
temp=temp2->next;
}
if(strcmp(x,"char")==0)
{
Node<char>* temp2=((Node<char>*)temp);
cout<<" "<<temp2->data;
strcpy(x,temp2->type);
temp=temp2->next;
}
}
}






};

void main(){
Link A;
A.makelist();

cout<<endl<<endl;


A.display();


cout<<endl;

}
Topic archived. No new replies allowed.