Thread: Accessing members of a class within a template

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    5

    Accessing members of a class within a template

    Hi everybody -
    I'm trying to develop simple list template that can create lists of various types of objects. My code is partially based on an example given in SAMS Teach Yourself C++ in 21 days.

    The following code includes my header for the template and also a short driver program. The header alone compiles just fine, but when I compile it with main(), I get errors (see end of post):

    Code:
    #include <iostream>
    
    using namespace std;
    
    //begin template header
    template <class Type>
    class List
    {
          public:
                 List():head(0),tail(0), theCount(0) {std::cout<<"Constructing list...";}
                 virtual ~List();
                 void insert(Type value);
                 void append(Type value);
                 int is_present(Type value);
                 int is_empty() const {return head == 0;}
                 int count() const {return theCount;}
                 void displayList() const;
          
          private:
                 class ListCell
                 {
                 public:
                        ListCell( Type value, ListCell * cell = 0): val(value), next(cell){}
                        Type val;
                        ListCell * next;
                 };
                 ListCell * head;
                 ListCell * tail;
                 int theCount;
    };
    
    
    //destructor
    template<class Type>
    List<Type>::~List()
    {
       ListCell * pCurrent = head;
       while (pCurrent != 0)
       {
          ListCell * pTemp = pCurrent->next;
          delete pCurrent;
          pCurrent = pTemp;
       }
    }
    
    //insert implementation - inserts a new value at the head of the list.
    template<class Type>
    void List<Type>::insert(Type value)
    {
       ListCell * pTemp = new ListCell(value, head);
       if (head == 0) pTemp = tail;
       pTemp = head;
       theCount++;
    }
    
    //append implementation - inserts a new value at the tail of the list.
    template<class Type>
    void List<Type>::append(Type value)
    {
       ListCell * pTemp = new ListCell(value);
       if (head == 0) pTemp = head;
       else tail->next = pTemp;
       tail = pTemp;
       theCount++;
    }
    
    //is_present implementation - checks to see if a given value is already present in the list
    template<class Type>
    int List<Type>::is_present(Type value)
    {
       if (head == 0)
       {
          return 0;
       }
       
       ListCell * pCurrent = head;
       while (pCurrent != 0)
       {
          if (*pCurrent.val == value)
             return 1;
          else
              pCurrent = *pCurrent.next;
       }
       
       return 0;
    }
    
    //displayList implementation - displays all current members of the list
    //assumes that any class/type passed to the template List has overloaded the << operator.
    template<class Type>
    void List<Type>::displayList() const
    {
       ListCell * pCurrent = head;
       for (int i = 1; pCurrent != 0; i++)
       {
          cout<<i <<":" <<*pCurrent.val;  //causes compiler error when instantiated in main()
          pCurrent = *pCurrent.next;  //causes compiler error when instantiated in main()
       }
    }
    //end header
    
    
    //driver program    
    int main()
    {
        int value;
        List<int> theList;
        
        cout<<"Enter a value to insert:";
        cin>> value;
        cin.ignore();
        theList.insert(value);
        cout<<"You have " <<theList.count() <<" members in your list."; //this line causes error
        theList.displayList();
    
        cin.get();
    }
    I'm using Dev-C++ 4.9.9.2. When I try to compile, I get the following errors:

    Line 96: error: request for member `val' in `pCurrent', which is of non-class type `List<int>::ListCell*'
    Line 97: error: request for member `next' in `pCurrent', which is of non-class type `List<int>::ListCell*'

    Somehow I can't access the members of the ListCell class... any help would be appreciated.

    Also, this is only my second thread on these forums - have I posted too much code?

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    You haven't specified ListCell as a templated class like you did for 'List'.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    5
    Thanks for responding, desolation. I tried making ListCell a templated class also, but I still receive the same error message. Here is the revised code:

    Code:
    #include <iostream>
    
    using namespace std;
    
    //begin template header
    template <class Type>
    class List
    {
          public:
                 List():head(0),tail(0), theCount(0) {std::cout<<"Constructing list...";}
                 virtual ~List();
                 void insert(Type value);
                 void append(Type value);
                 int is_present(Type value);
                 int is_empty() const {return head == 0;}
                 int count() const {return theCount;}
                 void displayList() const;
          
         private:
                 template <class T>
                 class ListCell
                 {
                 public:
                        ListCell( T value, ListCell * cell = 0): val(value), next(cell){}
                        Type val;
                        ListCell * next;
                 };
                 ListCell<Type> * head;
                 ListCell<Type> * tail;
                 int theCount;
    };
    
    
    //destructor
    template<class Type>
    List<Type>::~List()
    {
       ListCell<Type> * pCurrent = head;
       while (pCurrent != 0)
       {
          ListCell<Type> * pTemp = pCurrent->next;
          delete pCurrent;
          pCurrent = pTemp;
       }
    }
    
    //insert implementation - inserts a new value at the head of the list.
    template<class Type>
    void List<Type>::insert(Type value)
    {
       ListCell<Type> * pTemp = new ListCell<Type>(value, head);
       if (head == 0) pTemp = tail;
       pTemp = head;
       theCount++;
    }
    
    //append implementation - inserts a new value at the tail of the list.
    template<class Type>
    void List<Type>::append(Type value)
    {
       ListCell<Type> * pTemp = new ListCell<Type>(value);
       if (head == 0) pTemp = head;
       else tail->next = pTemp;
       tail = pTemp;
       theCount++;
    }
    
    //is_present implementation - checks to see if a given value is already present in the list
    template<class Type>
    int List<Type>::is_present(Type value)
    {
       if (head == 0)
       {
          return 0;
       }
       
       ListCell<Type> * pCurrent = head;
       while (pCurrent != 0)
       {
          if (*pCurrent.val == value)
             return 1;
          else
              pCurrent = *pCurrent.next;
       }
       
       return 0;
    }
    
    //displayList implementation - displays all current members of the list
    //assumes that any class/type passed to the template List has overloaded the << operator.
    template<class Type>
    void List<Type>::displayList() const
    {
       ListCell<Type> * pCurrent = head;
       for (int i = 1; pCurrent != 0; i++)
       {
          cout<<i <<":" <<*pCurrent.val;
          pCurrent = *pCurrent.next;
       }
    }
    //end header
    
    
    //driver program    
    int main()
    {
        int value;
        List<int> theList;
        
        cout<<"Enter a value to insert:";
        cin>> value;
        cin.ignore();
        theList.insert(value);
        cout<<"You have " <<theList.count() <<" members in your list.";
        theList.displayList();
    
        std::cin.get();
    }
    Still the same error as before. Is this what you meant, desolation?

    Any further thoughts out there? Again, all help is greatly appreciated.

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Code:
    *pCurrent.val
    The member access operator has a higher precedence than the dereference operator, so this code tries to access the val member of pCurrent and dereference that. Of course, a pointer has no members, so it complains.

    Use the indirect member access operator instead:
    [cod]pCurrent->val[/code]

    The other error is for the same reason.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Registered User
    Join Date
    Nov 2005
    Posts
    18
    I don't know if it can be usefull but I post what I did with the same exercise of the same book. If I remember, there was a problem with Display and for returning an array, so I replaced it by a vector.
    Code:
    #include <iostream>
    using namespace std;
    #include <string>
    #include <vector>
    template<class T>
    class List
    {
    public:
    List():head(0),tail(0),theCount(0){}
    virtual~List();
    void insert( T value );
    void append( T value );
    int is_present( T value) const;
    int is_empty( ) const{ return head == 0; }
    int count() const { return theCount; }
    void List_Display();
    T List_getValues()const;
    vector<T> List_getValues_array()const;
    void List_Count() { cout<<" Count is : "<<theCount<<endl;}
    int List_Count1()const { return theCount;}
    template<class T>
    friend int operator== (const T& lhs,const T& rhs );
    private:
    class ListCell
    {
    public:
    ListCell( T value, ListCell * cell = 0): val(value),
    next(cell) {}
    T val;
    ListCell * next;
    T getValue() const { return val; }
    void display(ListCell * pt)
    {cout<<" Value is : "<<pt->getValue()<<endl; }
    };
    ListCell * head;
    ListCell * tail;
    int theCount;
    };
    template<class T>
    List<T> :: ~List()
    {
    ListCell * pt = head;
    while(pt)
    {
    ListCell * tmp = pt;
    pt =pt->next;
    delete tmp;
    }
    head = 0;
    tail = 0;
    }
    template<class T>
    void List<T> :: insert(T value ) 
    {
    ListCell * pt = new ListCell( value, head );
    if( head==0) tail = pt;
    head = pt;
    theCount++;
    }
    template<class T>
    void List<T> :: append(T value ) 
    {
    ListCell * pt = new ListCell( value);
    if( head==0) head = pt;
    else {tail->next = pt;}
    tail = pt;
    pt->next = 0;
    theCount++;
    }
    template<class T>
    int List<T> :: is_present( T value ) const
    {
    if(head==0) return 0;
    if(head->val==value) return 1; ListCell * pt = head->next;
    for(;pt != tail; pt = pt->next )
    if(pt->val==value) return 1;
    
    return 0;
    } 
    template<class T>
    void List<T> :: List_Display()
    {
    ListCell * pt = head;
    while(pt!=tail->next)
    {
    cout<<" Value is : "<<pt->getValue()<<endl;
    pt = pt->next;
    }
    }
    template<class T>
    T List<T> :: List_getValues()const
    {
    T value;
    T value_array[100];
    ListCell * pt = head;
    while(pt!=tail->next)
    {
    value += pt->getValue();
    pt = pt->next;
    }
    for(int i=0;i<=theCount;i++){if(pt!=tail->next){value_array[i]=pt->getValue();pt=pt->next;}}
    return value;
    //return value_array;
    }
    template<class T>
    vector<T> List<T> :: List_getValues_array()const
    {
    vector<T>val_vect;
    T value_array[100];
    ListCell * pt = head;
    
    for( int i=0; i<=theCount; i++ )
    {
    if(pt!=tail->next) 
    { value_array[i] = pt->getValue();
    val_vect.push_back(value_array[i]);
    cout<<" "<<value_array[i];
    pt = pt->next; }
    }
    //return value_array[0];
    return val_vect;
    }
    
    
    
    
    template<class T>
    int operator== (const T& lhs,const T& rhs )
    {//compare lengths first
    T value1; T value2;
    if( lhs.theCount != rhs.theCount ) 
    return 0;//lengths differ 
    if( lhs.List_getValues()!= rhs.List_getValues() )
    return 0;
    return 1;//if they dont differ , they must match
    }
    
    class cat
    { };
    int main()
    {
    List<string> test;
    List<cat> test1;
    List<int> test2;
    test.List_Count();
    test.append("qw");
    test.List_Count();
    test.insert("yu");test.List_Count();
    test.append("az");test.List_Count();
    test.insert("kim");test.List_Count();
    test.List_Display();
    
    cout<<'\n';
    test2.List_Count();
    test2.append(786);test2.List_Count();
    test2.append(9000);test2.List_Count();
    test2.List_Display();
    
    cout<<'\n';
    List<string> test3; 
    test3 = test;
    test3.List_Display();
    if( test3 == test ) cout<< " \n1111 ";
    else cout<<" \n0000 ";
    
    cout<<test.List_getValues();
    
    vector<string>t = test.List_getValues_array();
    vector<string>t3 = test3.List_getValues_array();
    
    cout<<'\n';
    for( int i = 0; 
    i < (test.List_Count1());
    i++ ) 
    cout<<t[i]<<" ";
    if( t == t3 ) cout<< " test = test3 ...\n";
    getchar(); return 0;
    }
    Last edited by Ken Fitlike; 10-02-2006 at 04:25 AM. Reason: added code tags

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You're using code tags incorrectly. Place [code] before the code and [/code] after it.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You can edit old posts, and the slash needs to go before the word code in the end tag.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The formatting is still completely broken. Preserving indentation is kind of the point of code tags.

    Annoying, ain't I?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User
    Join Date
    Nov 2005
    Posts
    18
    I have deleted my last message since the first has been corrected but frankly I have not the sense that the formatting is especially broken? thanks again.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You have absolutely no indentation. It is impossible, without counting braces, to tell the structure of the code. So yes, it is broken.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User
    Join Date
    Nov 2005
    Posts
    18
    I see what you mean now, that's a mistake I did when working with Dreamweaver, but I didn't write my code like this. And I made the same mistake with the other pages of code I put on my site!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function template has already been defined
    By Elysia in forum C++ Programming
    Replies: 19
    Last Post: 04-14-2009, 10:17 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Replies: 8
    Last Post: 07-24-2006, 08:14 AM
  4. Accessing members of parent class
    By Snip in forum C++ Programming
    Replies: 7
    Last Post: 06-29-2006, 01:28 PM
  5. help with template class using a template node
    By aciarlillo in forum C++ Programming
    Replies: 11
    Last Post: 06-02-2005, 05:46 PM