Advertisement

Template linker errors

Started by February 27, 2002 08:37 PM
2 comments, last by OOProgrammer 22 years, 6 months ago
Alright, I''m getting linker errors from this infinite array class I stole from Practical C++ Programming and decided to templatize for practice. Specifically, I get these two errors multiple times:
undefined reference to `infinite_array::~infinite_array(void)''
undefined reference to `infinite_array::operator[](unsigned int)'' 
I can''t figure out why (obviously) and I even checked my work against my brand-new C++ reference, which had nothing specific to say about templates and errors of this type. Here is the definition of the class and its one constant(in a file called ia.h):
  // Number of elements to store in each cell of the infinite array

const unsigned int BLOCK_SIZE = 100;

template <class datatype>
class infinite_array {
   public:
      // Default constructor

      infinite_array(void)
      {
         next = NULL;
         memset(data, ''\0'', sizeof(data));
      }
      // Copy constructor

      infinite_array(const infinite_array &);
      // Default destructor

      ~infinite_array(void);
      // Return a reference to an element of the array

      datatype &operator[] (const unsigned int index);
   private:
      // The data for this block

      datatype data[BLOCK_SIZE];
      // Pointer to the next array

      class infinite_array *next;
};  
Also, here is the code for the two functions which are acting up(from a file named, strangely enough, ia.cpp):
  extern const unsigned int BLOCK_SIZE;

template<class datatype>
datatype &infinite_array<datatype>::operator [] (const unsigned int index)
{
   // Pointer to the current bucket

   class infinite_array *current_ptr;

   int current_index;   // Index we are working with


   current_ptr = this;
   current_index = index;

   while (current_index >= BLOCK_SIZE) {
      if (current_ptr->next == NULL) {
         current_ptr->next = new infinite_array;
         if (current_ptr->next == NULL) {
            cerr << "Error: Out of memory\n";
            exit(8);
         }
      }
      current_ptr = current_ptr->next;
      current_index -= BLOCK_SIZE;
   }
   return (current_ptr->data[current_index]);
}

template <class datatype>
infinite_array<datatype>::~infinite_array(void)
{
   /*
    * Note: We use a cute trick here.
    *
    * Because each bucket in the infinite array is an
    * infinite array itself, when we destroy next, it
    * will destroy all that bucket''s "next"s and so
    * on recursively clearing the entire array.
    */
   if (next != NULL) {
      delete next;
      next = NULL;
   }
}  
FYI I have #include''d ia.h in ia.cpp, and ia.h is included in my main.cpp. I hope this post isn''t too long...thanks for any help or suggestions. --------------------------------- "It''s groin-grabbingly transcendent!" - Mr. Gamble, my teacher, speaking of his C++ AP class
-----------------------------------"Is the size of project directly proportional to the amount of stupidity to be demonstrated?" -SabreMan
Template class declarations AND template class member functions must be in the header file together.

Invader X
Invader''s Realm
Advertisement
Thanks. I tried that, but I'll try it again.

EDIT: I feel stupid. I must have tried that but forgot to remove the ia.cpp file from my project. Thanks again!

Edited by - OOProgrammer on February 28, 2002 1:19:45 AM
-----------------------------------"Is the size of project directly proportional to the amount of stupidity to be demonstrated?" -SabreMan
You know, it doesn't _have_ to be all in the header.
I usually do somehing like this:

Class.h
    // Prototype of the Class class, Class.h#ifndef CLASS_H_#define CLASS_H_template <class Type>class Class{public:Class();~Class();void foo( Type arg );private:Type myType;static Type myStaticType;};#include "Class.tem"#endif    


Class.tem (a text file!)

        // Implementation of the Class class, Class.tem#include <iostream>using std::cout;using std::endl;template <class Type>Type Class::myStaticType; template <class Type>Class::Class() : myType(0){}template <class Type>Class::~Class(){}template <class Type>void Class::foo( Type arg ){cout << "Class::foo() called, arg = " << arg << endl;}    



Basically, we trick the compiler into thinking it's looking at a single file.

I like how it maintains my file structure and separates protypes and implementation.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]

Edited by - DoomX on March 1, 2002 7:19:52 PM
There are 10 kinds of people in the world: those who get binary, and those who don't...

This topic is closed to new replies.

Advertisement