Thread: Unresolved external with template function

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    22

    Unresolved external with template function

    I am trying to use a template function to overload the >> stream operator but keep getting unresolved external errors (VC++ 6.0).

    The function definition and declaration are:
    Code:
    // .h file **********************
    #include <fstream>
    
    using namespace std;
    
    class BinStreamIn : public ifstream 
    {
       
    public:
       BinStreamIn( const char *inputFileName );
       void ReadBytes(void *inputBytes, int numOfBytesToInput);
       template <class T> BinStreamIn & operator>> (T &inputValue);
     .
     .
     .
    }   
    
    //.cpp file ***********************
    template <class T> BinStreamIn & BinStreamIn::operator>> (T &inputValue) 
    {
       BinStreamIn::ReadBytes( &inputValue, sizeof(inputValue) );
      return *this;
    
    } // end function BinStreamIn::operator>>
    
    --------------------------
    Linking...
    DataStreamReader.obj : error LNK2001: unresolved external symbol "public: class BinStreamIn & __thiscall BinStreamIn::operator>>(unsigned short &)" (??5BinStreamIn@@QAEAAV0@AAG@Z)
    Release/FEP.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.
    Any ideas?

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Cut that bit of templated code you have from the .cpp file and paste it into the .h file... get rid of the .cpp file from your project if that is the only bit of code in that file.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    May 2005
    Posts
    22
    There is other code in the cpp file so I need to keep it. Why does the templated function need to be in the h file though? Doesn't a #include get you what you need?

    I put the template function in the .h file and it does compile, but I now get the following error in the function that calls it:
    Code:
    DataStreamReader.cpp
    C:\ABI Workspace\MPI\MPI_Split_exes\FEP\DataStreamReader.cpp(29) : error C2679: binary '>>' : no operator defined which takes a right-hand operand of type 'unsigned short' (or there is no acceptable conversion)
    Now it seems to think I'm trying to use the binary shift operator instead of my overloaded extraction operator.

    Here is the function... (VALUE_TYPE is typedef'd as an unsigned short int)
    Code:
    #include "DataStreamReader.h"
    
    int DataStreamReader::GetValues(BinStreamIn dataFile, VALUE_TYPE values[]) 
    {
       // Local Variables
       unsigned int counter = 0;
       
    //   while((counter < MAX_VALS) && (dataFile >> values[counter]))
       while(counter < MAX_VALS)
       {
          dataFile >> values[counter];  //Here's the use of the >> operator 
          counter++;
          cout << "#vals = " << counter - 1 << "  value read = " << (VALUE_TYPE)values[counter - 1] << endl;
       }
          
       return counter;
       
    } // end function GetValues

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Did you remember to #include the header that contains BinStreamIn? The code you posted compiles fine for me with some added stuff around it. You'll probably want to post more code to see the problem.

    The reason you need to put all the code for a templated class into the header file is that the code is just a template and the compiler needs to compile the code with each type that will be used with it. If you add it to the header file included by files that use it, then the compiler will see which types are used with it and compile them properly.

    BTW, I don't think you should be passing the stream by value. You probably meant to make that a reference argument.

  5. #5
    Registered User
    Join Date
    May 2005
    Posts
    22
    You are right about passing by reference. That's the way I had it initially but tried passing by value when I couldn't find any fix for this problem. I forgot to change it back.

    I do have a #include to BinStreamIn.h in DataStreamReader.h
    Code:
    #include "BinStreamIn.h"
    
    class DataStreamReader
    {
    public:
       int GetValues(BinStreamIn &dataFile, VALUE_TYPE values[]);
    };
    Code:
    #include "DataStreamReader.h"
    
    int DataStreamReader::GetValues(BinStreamIn &dataFile, VALUE_TYPE values[]) 
    {
       // Local Variables
       unsigned int counter = 0;
       
       while(counter < MAX_VALS)
       {
          dataFile >> values[counter];
          counter++;
          cout << "#vals = " << counter - 1 << "  value read = " << (VALUE_TYPE)values[counter - 1] << endl;
       }
          
       return counter;
       
    } // end function GetValues
    Here's BitStreamIn.h
    Code:
    #include "..\FEP\fep.h"
    #include <fstream>
    
    using namespace std;
    
    class BinStreamIn : public ifstream 
    {
       
    public:
       BinStreamIn( const char *inputFileName );
       void ReadBytes(void *inputBytes, int numOfBytesToInput);
       template <class T> BinStreamIn & operator>> (T &inputValue);
       
    }; // end class BinStreamIn
    
    
    //////////////////////////////////////////////////////////////////////////////// 
    // 
    //  Function Name : ReadBytes 
    // 
    //////////////////////////////////////////////////////////////////////////////// 
    void BinStreamIn::ReadBytes(void *inputBytes, int numOfBytesToInput) 
    {
    
      // Local Variables
      bool somethingIsWrongWithTheVoidPointer = !inputBytes;
      bool invalidNumOfBytesProvided = (numOfBytesToInput <= 0);
    
      if (somethingIsWrongWithTheVoidPointer || invalidNumOfBytesProvided) 
      {
        return;
      } // end if
      else 
      {
        read((char *)inputBytes, numOfBytesToInput);
      } // end else
    
    } // end function BinStreamIn::ReadBytes
    
    //////////////////////////////////////////////////////////////////////////////// 
    // 
    //  Function Name : operator>> 
    // 
    //////////////////////////////////////////////////////////////////////////////// 
    template <class T> BinStreamIn & BinStreamIn::operator>> (T &inputValue) 
    {
       BinStreamIn::ReadBytes( &inputValue, sizeof(inputValue) );
      return *this;
    
    }; // end function BinStreamIn::operator>>
    I did find that if I use the alternate method of calling the overloaded >> operator like this:
    Code:
          dataFile.operator >>(values[counter]);
    that I get a different error.
    Code:
    DataStreamReader.cpp(28) : error C2893: Failed to specialize function template 'class BinStreamIn &__thiscall BinStreamIn::operator >>(T &)'
            With the following template arguments:
            'unsigned short'
    Hopefully that's enough code to spot a problem.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Book's code: Problematic
    By RoD in forum Game Programming
    Replies: 14
    Last Post: 01-21-2003, 09:08 AM