Thread: I need help with templates!

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    34

    I need help with templates!

    Hello, this is sort of a follow up to my last question. I figured out my problem there, and it was I had to use templates. My problem now is this is my first time using templates, and here are my errors:

    runSortedLinkedList.cxx: In function `int main()':
    runSortedLinkedList.cxx:49: error: no matching function for call to `FileToList
    (SortedType<ItemType>&, std::ifstream&, std::ofstream&)'
    runSortedLinkedList.cxx:50: error: no matching function for call to `ListToFile
    (SortedType<ItemType>&, std::ofstream&)'
    runSortedLinkedList.cxx: In function `void FileToList(SortedType<int>&,
    std::ifstream&, std::ofstream&)':
    runSortedLinkedList.cxx:69: error: no matching function for call to `
    SortedType<int>::InsertItem(ItemType&)'
    SortedLinkedList.h:49: error: candidates are: void
    SortedType<ItemType>::InsertItem(ItemType) [with ItemType = int]
    runSortedLinkedList.cxx:71: error: no matching function for call to `ListToFile
    (SortedType<int>&, std::basic_ofstream<char, std::char_traits<char> >&)'
    runSortedLinkedList.cxx:79: error: no matching function for call to `ListToFile
    (SortedType<int>&, std::basic_ofstream<char, std::char_traits<char> >&)'
    runSortedLinkedList.cxx:84: error: no matching function for call to `
    SortedType<int>::DeleteItem(ItemType&)'
    SortedLinkedList.h:56: error: candidates are: void
    SortedType<ItemType>::DeleteItem(ItemType) [with ItemType = int]
    runSortedLinkedList.cxx:86: error: no matching function for call to `ItemType::
    GetItemFromFile(ItemType&)'
    ItemType.h:39: error: candidates are: char
    ItemType::GetItemFromFile(std::ifstream&)
    runSortedLinkedList.cxx: In function `void ListToFile(SortedType<int>&,
    std::ofstream&)':
    runSortedLinkedList.cxx:105: error: no matching function for call to `
    SortedType<int>::GetNextItem(ItemType&)'
    SortedLinkedList.h:69: error: candidates are: void
    SortedType<ItemType>::GetNextItem(ItemType&) [with ItemType = int]


    I know I should have most of my code correct, it's just in my runSortedLinkedList file that I am having problems declaring it. Thank you for your help. Here is my code:
    Code:
    SortedType.h
    
    #include "ItemType.h"
    
    template<class ItemType>
    struct NodeType
    {
      ItemType info;
      NodeType* next;
    };
    
    template<class ItemType> 
    class SortedType
    {
     public:
      SortedType();
      // Constructor
      // Postcondition: Empty list is created
    
      ~SortedType();
      // Destructor
      // Postcondition: List is destroyed
    
      SortedType(const SortedType& otherList);
      // Copy-constructor
      // Postcondition: List is created as a duplicate of otherList
    
      bool IsFull() const;
      // Determines whether list is full.
      // Post: Function value = (list is full)
    
      int  LengthIs() const;
      // Determines the number of elements in list.
      // Post: Function value = number of elements in list.
    
      void MakeEmpty();
      // Initializes list to empty state.
      // Post:  List is empty.
    
      void RetrieveItem(ItemType& item, bool& found);
      // Retrieves list element whose key matches item's key 
      // (if present).
      // Pre:  Key member of item is initialized.
      // Post: If there is an element someItem whose key matches 
      //       item's key, then found = true and item is a copy 
      //       of someItem; otherwise found = false and item is 
      //       unchanged. 
      //       List is unchanged.
    
      void InsertItem(ItemType item); 
      // Adds item to list.
      // Pre:  List is not full.
      //       item is not in list. 
      // Post: item is in list 
      // (added)  //       list order is preserved
    
      void DeleteItem(ItemType item);
      // Deletes the element whose key matches item's key.
      // Pre:  Key member of item is initialized.
      //       One and only one element in list has a key matching
      //       item's key.
      // Post: No element in list has a key matching item's key.
    
    
      void ResetList();
      // Initializes current position to end of list for iteration 
      // through list.
      // Post: Current position is at end of list.
    
      void GetNextItem(ItemType& item);
      // Gets the next element in list.
      // Pre:  
      // Post: If Current position is at end,  currentPos points to head of list, 
      //       else item is  copy  of  element at current position. 
      //       Advance current position.
    
      void Print(); 
    
     private:
      NodeType<ItemType>* listData;
      int length;
      NodeType<ItemType>* currentPos;
    };
     
    runSortedType.cxx
    #include "SortedLinkedList.h"
    #include <fstream>
    
    using namespace std;
    template<class ItemType>
    void FileToList(SortedType<int>& intList, ifstream& inFile, ofstream& 
    outFile);
    // PURPOSE: To take an item from the GetItemFromFile function, and to add
    // it if addOrDelete was 'A' or delete it if addOrDelete was 'D'. Also to 
    // print error messages accordingly.
    // INPUT: intList, inFile
    // PRE: intList is declared, inFile is OK, outFile is OK
    // OUTPUT: outFile
    // POST: An item(s) were written to intList with an error message if 
    // according
    // NOTE: none
    
    template <class ItemType>
    void ListToFile(SortedType<int>& intList, ofstream& outFile);
    // PURPOSE: To print the list to a file as long as data exists in the list
    // INPUT: intList
    // PRE: intList is declared and OK, outFile is OK
    // OUTPUT: outFile
    // POST: All items are written to the outFile
    // NOTE: none
    
    int main()
    {
       ifstream inFile;
       ofstream outFile;
       SortedType<int> intList;
    
       FileToList(intList, inFile, outFile);
       ListToFile(intList, outFile);
    
       return 0;
    }
    
    void FileToList(SortedType<int>& intList, ifstream& inFile, ofstream& 
    outFile)
    {
       ItemType item;
       char addOrDelete;
    
       inFile.open("in.data");
       intList.MakeEmpty();
       addOrDelete = item.GetItemFromFile(inFile);
       while (inFile)
       {
          if (addOrDelete == 'A')
          {
             if (!intList.IsFull())
                intList.InsertItem(item);
             else{
                ListToFile(intList, outFile);
                item.PrintLstFullErr(outFile);
             }
             addOrDelete = item.GetItemFromFile(inFile);
          }
          else if (addOrDelete == 'D')
          {
             if(intList.LengthIs() == 0){
                ListToFile(intList, outFile);
                item.PrintEmptyLstErr(outFile);
             }
             else
             {
                intList.DeleteItem(item);
             }
             addOrDelete = item.GetItemFromFile(item);
          }
       }
    }
    
    void ListToFile(SortedType<int>& intList, ofstream& outFile)
    {
       ItemType item;
       int length;
    
       outFile.open("out.data");
       intList.ResetList();
       length = intList.LengthIs();
      
       outFile << "STUDENT ID" << setw(6) << "EXAM1" << setw(10) << "EXAM2"
               << setw(9) << "FINAL" << setw(9) << "PROG" << setw(14)
               << "QUIZZES" << endl;
       for (int count = 1; count <= length; count++)
       {
          intList.GetNextItem(item);
          item.WriteItemToFile(outFile);
       }
    }
    I have not included my ItemType files (which you shouldn't really need) or my SortedLinkedList.cxx (which you may need). Thanks again!!

  2. #2
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    Quote Originally Posted by advocation
    Hello, this is sort of a follow up to my last question. I figured out my problem there, and it was I had to use templates.
    Code:
    using namespace std;
    template<class ItemType>
    void FileToList(SortedType<int>& intList, ifstream& inFile, ofstream& 
    outFile);
    //This indicates that your fuction prototype is templated on ItemType
    
    template<class ItemType>
    void FileToList(SortedType<int>& intList, ifstream& inFile, ofstream& 
    outFile);
    //This is the type that you are passing, it is a regular type just like int
    because SortedType<> has already been given a type. It is a 
    particular instantiation of the template class.
    
    template<class ItemType>
    void FileToList(SortedType<ItemType>& list, ifstream& inFile, ofstream& 
    outFile);
    
    //is likely the prototype you want, remember that 
    the definition must be visable to everyone who calls FileToList, so 
    there is somewhat less reason to have prototypes and function 
    definitions seperate.
    P.S. Quick show of hands, how many of you keep pressing F7 to reply to a post where you wrote a lot of code? Just me huh? I think I need to get outside more.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Posts
    34
    Great!! Thank you so much, but now I have one problem that was not identified before. I have a function returning a character in ItemType so that is why I belive that I am getting this error:
    runSortedLinkedList.cxx: In function `void FileToList(SortedType<ItemType>&,
    std::ifstream&, std:fstream&)':
    runSortedLinkedList.cxx:86: error: no matching function for call to `ItemType::
    GetItemFromFile(ItemType&)'
    ItemType.h:39: error: candidates are: char
    ItemType::GetItemFromFile(std::ifstream&)

    Basically why I am doing this is because I need to know if the first character passed is an 'A' or a 'D'. This tells me if i should delete or add to the stack. Any idea around this? In ItemType the declaration of the function is
    char ItemType::getItemFromFile(ifstream& inFile)
    If you need the ItemType files, just let me know. Thanks

  4. #4
    Registered User
    Join Date
    Mar 2005
    Posts
    34
    Nevermind, I got that to work, my stupid mistake. But now, since I put everything in i get these error codes :
    /tmp/ccbyVii5.o(.text+0x43): In function `main':
    : undefined reference to `SortedType<int>::SortedType[in-charge]()'
    /tmp/ccbyVii5.o(.text+0x63): In function `main':
    : undefined reference to `void FileToList<int>(SortedType<int>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)'
    /tmp/ccbyVii5.o(.text+0x7c): In function `main':
    : undefined reference to `void ListToFile<int>(SortedType<int>&, std::basic_ofstream<char, std::char_traits<char> >&)'
    /tmp/ccbyVii5.o(.text+0x8e): In function `main':
    : undefined reference to `SortedType<int>::~SortedType [in-charge]()'
    /tmp/ccbyVii5.o(.text+0xdc): In function `main':
    : undefined reference to `SortedType<int>::~SortedType [in-charge]()'
    /tmp/ccbyVii5.o(.text+0x17f): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::MakeEmpty()'
    /tmp/ccbyVii5.o(.text+0x1ce): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::IsFull() const'
    /tmp/ccbyVii5.o(.text+0x20e): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::InsertItem(ItemType)'
    /tmp/ccbyVii5.o(.text+0x221): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `void ListToFile<ItemType>(SortedType<ItemType>&, std::basic_ofstream<char, std::char_traits<char> >&)'
    /tmp/ccbyVii5.o(.text+0x265): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::LengthIs() const'
    /tmp/ccbyVii5.o(.text+0x27a): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `void ListToFile<ItemType>(SortedType<ItemType>&, std::basic_ofstream<char, std::char_traits<char> >&)'
    /tmp/ccbyVii5.o(.text+0x2ca): In function `FileToList(SortedType<ItemType>&, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>:eleteItem(ItemType)'
    /tmp/ccbyVii5.o(.text+0x32d): In function `ListToFile(SortedType<ItemType>&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::ResetList()'
    /tmp/ccbyVii5.o(.text+0x33b): In function `ListToFile(SortedType<ItemType>&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::LengthIs() const'
    /tmp/ccbyVii5.o(.text+0x46b): In function `ListToFile(SortedType<ItemType>&, std::basic_ofstream<char, std::char_traits<char> >&)':
    : undefined reference to `SortedType<ItemType>::GetNextItem(ItemType&)'
    collect2: ld returned 1 exit status

    I can't read them, gibberish to me. Any help?

  5. #5
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    Those are linker errors, basically you need to be sure that every file that calls a function can see the definition, not just the name. If your sorted type header file has a cpp file compiled seperately then that file cannot contain any templates. You can think of them as something like macros, except there's fancy hacky things going on in the background so that only one function for each type that you use is included. Without seeing the source that's my guess at least.

  6. #6
    Registered User
    Join Date
    Mar 2005
    Posts
    34
    Ok, I already have my SortedLinkedList.h and my runSortedLinkedList.cxx up, so here is the rest of the code:
    Code:
    SortedLinkedList.cxx
    #include "SortedLinkedList.h"
    
    template<class ItemType>
    SortedType<ItemType>::SortedType()  // Class constructor
    {
      length = 0;
      listData = NULL;
    }
    
    template<class ItemType>
    SortedType<ItemType>::~SortedType()
    // Post: List is empty; all items have been deallocated.
    {
      MakeEmpty();
    }
    
    template<class ItemType>
    SortedType<ItemType>::SortedType(const SortedType& otherList)
    // Copy-constructor
    // Postcondition:
    //     IF otherList.listData == NULL
    //         listData == NULL
    //     ELSE
    //         listData points to a new linked list that is a copy of
    //         the linked list pointed to by otherList.listData
    {
        NodeType<ItemType>* fromPtr;  // Pointer into list being copied from
        NodeType<ItemType>* toPtr;    // Pointer into new list being built
        if(otherList.listData == NULL)
        {
            listData = NULL;
            return;
        }
        // Copy first node
        fromPtr = otherList.listData;
        listData = new NodeType<ItemType>;
        listData->info = fromPtr->info;
    
        // Copy remaining nodes
    
        toPtr = listData;
        fromPtr = fromPtr->next;
        while (fromPtr != NULL)
        {
            toPtr->next = new NodeType<ItemType>;
            toPtr = toPtr->next;
            toPtr->info = fromPtr->info;
            fromPtr = fromPtr->next;
        }
        toPtr->next = NULL;
    }
    
    /* bool SortedType::IsFull() const
    // Returns true if there is no room for another ItemType
    //  on the free store; false otherwise.
    {
      NodeType* location;
      try
      {
        location = new NodeType;
        delete location;
        return false;
      }
      catch(bad_alloc exception)
      {
        return true;
      }
    } */
    
    template<class ItemType>
    bool SortedType<ItemType>::IsFull() const
    // Returns true if there is no room for another ItemType
    // object on the free store; false otherwise.
    {
      NodeType<ItemType>* ptr;
    
      ptr = new NodeType<ItemType>;
      if (ptr == NULL)
        return true;
      else
      {
        delete ptr;
        return false;
      }
    }
    
    template<class ItemType>
    int SortedType<ItemType>::LengthIs() const
    // Post: Number of items in the list is returned.
    {
      return length;
    }
    
    template<class ItemType>
    void SortedType<ItemType>::MakeEmpty()
    // Post: List is empty; all items have been deallocated.
    {
      NodeType<ItemType>*
      tempPtr;
    
      while (listData != NULL) // traverse list, deallocating each node in turn
      {
        tempPtr = listData;
        listData = listData->next;
        delete tempPtr;
      }
      length = 0; // to agree with the fact that all nodes are deallocated
    }
    
    template<class ItemType>
    void SortedType<ItemType>::DeleteItem(ItemType item)
    // Pre:  item's key has been initialized.
    //       An element in the list has a key that matches item's.
    // Post: No element in the list has a key that matches item's.
    {
      NodeType<ItemType>* location = listData;
      NodeType<ItemType>* tempLocation;
    
      // Locate node to be deleted.
      if (item == listData->info)
      {
        tempLocation = location;
        listData = listData->next;          // Delete first node.
      }
      else
      {
        while (!(item==(location->next)->info))
          location = location->next;
    
        // Delete node at location->next
        tempLocation = location->next;
        location->next = (location->next)->next;
      }
      delete tempLocation;
      length--;
    }
    
    template<class ItemType>
    void SortedType<ItemType>::ResetList()
    // Post: Current position has been initialized to AtEnd
    {
      currentPos = NULL;
    }
    
    template<class ItemType>
    void SortedType<ItemType>::RetrieveItem(ItemType& item, bool& found)
    {
      bool moreToSearch;
      NodeType<ItemType>* location;
    
      location = listData;
      found = false;
      moreToSearch = (location != NULL);
    
      while (moreToSearch && !found)
      {
        if (location->info < item)
        {
          location = location->next;
          moreToSearch = (location != NULL);
        }
        else if (item == location->info)
        {
          found = true;
          item = location->info;
        }
        else
          moreToSearch = false;
      }
    }
    
    template<class ItemType>
    void SortedType<ItemType>::InsertItem(ItemType item)
    {
      NodeType<ItemType>* newNode;  // pointer to node being inserted
      NodeType<ItemType>* predLoc;  // trailing pointer
      NodeType<ItemType>* location; // traveling pointer
      bool moreToSearch;
    
      location = listData;
      predLoc = NULL;
      moreToSearch = (location != NULL);
    
      // Find insertion point.
      while (moreToSearch)
      {
        if (location->info < item)
        {
          predLoc = location;
          location = location->next;
          moreToSearch = (location != NULL);
        }
        else
          moreToSearch = false;
     }
      // Prepare node for insertion
      newNode = new NodeType<ItemType>;
      newNode->info = item;
    
      // Insert node into list.
      if (predLoc == NULL)         // Insert as first
      {
        newNode->next = listData;
        listData = newNode;
      }
      else
      {
        newNode->next = location;
        predLoc->next = newNode;
      }
      length++;
    }
    
    template<class ItemType>
    void SortedType<ItemType>::GetNextItem(ItemType& item)
    // Pre:  Current position is defined.
    //       Element at current position is not last in list.
    // Post: Current position has been updated; item is current item.
    {
      if (currentPos == NULL) //Wrap at end of list
        currentPos = listData;
    
      item = currentPos->info;
      currentPos = currentPos->next;
    }
    
    template<class ItemType>
    void SortedType<ItemType>::Print()
    {
       currentPos = listData;
    
       while(currentPos != NULL)
       {
           cout << currentPos->info << " ";
           currentPos = currentPos->next;
       }
    }
    
    ItemType.h
    #include <fstream.h>
    #include <iostream.h>
    #include <iomanip.h>
    
    const int MAX_ITEMS = 10;
    enum  RelationType {LESS, EQUAL, GREATER};
    
    class ItemType
    {						
      public :
        
        ItemType();
    //  PURPOSE: To set each variable with a default value
    //  INPUT: none
    //  PRE: all variables exist
    //  OUTPUT: none
    //  POST: default data is assigned
    //  NOTE: none
    
        ItemType(int id, float exam1, float exam2, float final, float prog, 
        float quizzes, char addOrDelete);   
    //  PURPOSE: This is used to initialize values to variables
    //  INPUT: id, exam1, exam2, final, prog, quizzes, addOrDelete
    //  PRE: all variables are assinged and ok
    //  OUTPUT: none
    //  POST: id, exam1, exam2, final, prog, quizzes, and addOrDelete are 
    //  assinged
    //  NOTE: none
    
        RelationType ComparedTo(ItemType) const;
    //  PURPOSE: This comapres one item of ItemType to another item to return 
    //  either greater, less, or equal
    //  INPUT: ItemType
    //  PRE: ItemType is valid and assinged
    //  OUTPUT: LESS, GREATER, or EQUAL
    //  POST: That less, greater, or equal is returned
    //  NOTE: none
    
        char GetItemFromFile(ifstream& inFile);
    //  PURPOSE: This will read the items from an inFile, and will also 
    //  determine what variables to read by it's first character
    //  INPUT: inFile
    //  PRE: inFile is opened and OK
    //  OUTPUT: addOrDelete
    //  POST: all variables are assinged and addOrDelete is returned
    //  NOTE: none
     
        void WriteItemToFile(ofstream& outFile) const;
    //  PURPOSE: This will write all variables (id, exam1, exam2, final, prog, 
    //  and quizzes, to an outFile
    //  INPUT: none
    //  PRE: outFile is opened and OK
    //  OUTPUT: outFile
    //  POST: all variables are assigned to the outFile
    //  NOTE: none
    
        void PrintLstFullErr(ofstream& outFile) const;
    //  PURPOSE: This will print the error message when the list is full and 
    //  is trying to be added too
    //  INPUT: none
    //  PRE: list is full and trying to be written to
    //  OUTPUT: outFile
    //  POST: error message is written to outFile
    //  NOTE: none
    
        void PrintEmptyLstErr(ofstream& outFile);
    //  PURPOSE: This will print an error message when the list is empty but
    //  a line is trying to be deleted from it
    //  INPUT: none
    //  PRE: list is empty and is trying to be deleted from
    //  OUTPUT: outFile
    //  POST: error message is written to the outFile
    //  NOTE: none
    
      private :		
        int id;
        float exam1;
        float exam2;
        float final;
        float prog;
        float quizzes;
        char addOrDelete;       
    } ;
    I understand perfectly what you are saying. My only problem is, I don't know how to fix it. I cannot put an include "ItemType.h" in my SortedLinkedList.cxx file, because I already have it in my SortedLinkedList.h file. I don't get why it wouldn't be seeing the definition of ItemType, because I have ItemType.h included in my SoretedLinkList.h file.

  7. #7
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    Part of the problem is that you have a template paramiter named ItemType, along with a class, that appears to be an ordinary class, named ItemType. Basically what it looks like you need to do is include SortedLinkedList.cxx in the header. The files that need to see all the
    templates are any file that calls them. ItemType.h gets a ItemType.cxx for all the methods, and you only need to link to the resulting object file. SortedList.h contains templates thus this:
    Code:
    template<class ItemType>
    SortedType<ItemType>::SortedType()  // Class constructor
    {
      length = 0;
      listData = NULL;
    }
    needs to be in every file that includes SortedList.h (at leas all those that construct a SortedType). Normally this is done by including all of the above in the header file SortedList.h, someday compilers may support export.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Templates from DLL or static library problem
    By mikahell in forum C++ Programming
    Replies: 2
    Last Post: 01-01-2008, 01:49 AM
  2. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-18-2005, 12:22 AM
  3. templates and inheritance problem
    By kuhnmi in forum C++ Programming
    Replies: 4
    Last Post: 06-14-2004, 02:46 AM
  4. When and when not to use templates
    By *ClownPimp* in forum C++ Programming
    Replies: 7
    Last Post: 07-20-2003, 09:36 AM