• Welcome to Valhalla Legends Archive.
 

Using templates

Started by iago, April 05, 2003, 01:30 PM

Previous topic - Next topic

iago

Ok, I'm writing a very basic memory management class for c++ (it's for homework, not for fun!) and I'm having a problem with using templates (they are the devil).  Anyway, here's the definition of my class:
template<class T> class MemObject
and later on, I want to send a call to my other class to allocate memory for whatever type of object they requested:
MemObject<class T>::MemObject()
{
   ref = allocateMemory(sizeof(T));

   if(ref == ERROR)
   {
      cout << "Error allocating memory!" << endl;
   }
}

where ref is just an integer that's used to identify the memory and reference it later.  My problem is that sizeof(T) causes a compile error, "r:\My Projects\C\School\cs216a4\memObject.cpp(20): error C2027: use of undefined type 'T'"

Obviously, I'm not using this template thing right, but I'm hoping somebody could tell me what I'm doing wrong :)

Thanks!
-iago
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


K

#1

template <class T>
MemObject<T>::MemObject()
{
  ref = allocateMemory(sizeof(T));

  if(ref == ERROR)
  {
     cout << "Error allocating memory!" << endl;
  }
}


You need to include the template declaration at the function level as well.

iago

Quote from: K on April 05, 2003, 02:11 PM

template <class T>
MemObject<T>::MemObject()
{
  ref = allocateMemory(sizeof(T));

  if(ref == ERROR)
  {
     cout << "Error allocating memory!" << endl;
  }
}


You need to include the template declaration at the function level as well.

Using exactly your code:
"r:\My Projects\C\School\cs216a4\memObject.cpp(19): error C2365: 'T' : redefinition; previous definition was a 'template parameter'"
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


K

I'm not getting that error. Here's what my code looks like.


// my test class
template <class T>
class MemObj
{
 public:
   int ref;
   MemObj();

};


template <class T>
MemObj<T>::MemObj()
{
    ref = allocateMemory(sizeof(T));

   if(ref == ERROR)
   {
        cout << "Error allocating memory!" << endl;
    }
}

Zakath

Yeah...the way K is doing it is the correct way. That error you're getting is really strange.
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.

iago

I had this:

// my test class
template <class T>
class MemObj
{
 public:
   int ref;
   MemObj();

};


template <class T>
MemObj<class T>::MemObj()
{
    ref = allocateMemory(sizeof(T));

   if(ref == ERROR)
   {
        cout << "Error allocating memory!" << endl;
    }
}


And it wasn't working.  What a kick in the ass! :-)

*applauds
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


iago

Ok, NOW this is pissing me off.  Here is my main function:
#include <iostream>
#include <string>
#include "memObject.h"
#include <math.h>
#include <stdio.h>
using namespace std;


struct testStruct
{
 int value;
 double d;
};

int main( int argc, char *argv[] )
{
   MemObject <testStruct> test;
}


This is from MemObject.h:
template<class T> class MemObject
{
 private:
     // reference to our object in memory
     // (equivolant to my "index")
     Ref ref;
     // used to tell us if this object is containing in another object of the same type (only)
     //MemObject<T> const *parent;

 public:
     // This function will allocate and create an object. The data must be set using operator->.
     // If there isn't enough room, garbage collection will be initiated. An error message will be printed
     // there's still no room following the collection.
     // The parameter is used to track linked structures; automatically set if you have nothing to track.
     MemObject( MemObject<T> const *theParent = NULL );

     // This function will guarantee that the reference to our object is removed when we go out of context.
     // This will occur when we exit a function -- this object disappears and hence our reference.
     ~MemObject();
[.......]


And this is how they're defined in my .cpp file:
// This function will allocate and create an object. The data must be set using operator->.
// If there isn't enough room, garbage collection will be initiated. An error message will be printed
// there's still no room following the collection.
// The parameter is used to track linked structures; automatically set if you have nothing to track.
template <class T> MemObject<T>::MemObject( MemObject<T> const *theParent )
{
   ref = allocateMemory(sizeof(T));

   if(ref == ERROR)
   {
      cout << "Error allocating memory!" << endl;
   }
}

// This function will guarantee that the reference to our object is removed when we go out of context.
// This will occur when we exit a function -- this object disappears and hence our reference.
MemObject<class T>::~MemObject()
{
   deleteMemory(ref);
}
[.....]


Here are my errors:
Quotecs216a4 error LNK2019: unresolved external symbol "public: __thiscall MemObject<struct testStruct>::~MemObject<struct testStruct>(void)" (??1?$MemObject@UtestStruct@@@@QAE@XZ) referenced in function _main
cs216a4 error LNK2019: unresolved external symbol "public: __thiscall MemObject<struct testStruct>::MemObject<struct testStruct>(class MemObject<struct testStruct> const *)" (??0?$MemObject@UtestStruct@@@@QAE@PBV0@@Z) referenced in function _main
cs216a4 fatal error LNK1120: 2 unresolved externals

Clearly, it doesn't think I've defined my contructor or destructor.  If I try to add any other functions, it doesn't think I've defined them either.  It actually seems like it's completely ignoring my .cpp file, but it's in the same directory and it generates MemObject.obj.  

What I'm thinking is that I'm making the same mistake on all the function definitions, but I'm not sure what that mistake is.  Any help would be appreciated :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Skywing

Quote from: iago on April 05, 2003, 04:32 PM
Ok, NOW this is pissing me off.  Here is my main function:
...
Clearly, it doesn't think I've defined my contructor or destructor.  If I try to add any other functions, it doesn't think I've defined them either.  It actually seems like it's completely ignoring my .cpp file, but it's in the same directory and it generates MemObject.obj.  

What I'm thinking is that I'm making the same mistake on all the function definitions, but I'm not sure what that mistake is.  Any help would be appreciated :)
Template definitions must be in every translation unit compiled, unless the export keyword is used.  Note that there are almost no C++ compilers which support the export keyword.

K

You need to fix your deconstructor the same way you fixed the constructor:


template <class T>
MemObject<T>::~MemObject()
{
   // ...
}

Zakath

Uhh...iago, you aren't CALLING the constructor when you create the object.

Should be:
MemObject<TestStruct> test( NULL );

or
MemObject<TestStruct> *test;
test = new MemObject<TestStruct>( NULL );

You get the idea?
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.

iago

Quote from: Zakath on April 05, 2003, 06:41 PM
Uhh...iago, you aren't CALLING the constructor when you create the object.

Should be:
MemObject<TestStruct> test( NULL );

or
MemObject<TestStruct> *test;
test = new MemObject<TestStruct>( NULL );

You get the idea?

Lies! When it's created on the stack, it's automatically called with the default constructor, I'm almost positive
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Yoni

Zakath lies. iago's constructor, although it has a parameter, is considered a default constructor because all the parameters have a default value.

Zakath

Hmm...

Nevermind then, seems I'm wrong :P
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.