0

Possible Duplicate:
Why can templates only be implemented in the header file?

I ran into this wall before, but I've no idea how to fix it. In g++ I get this error whenever I try to create an object of class BinaryTree:

/home/bej0843/cs261/Assignment1/main.cpp:9: undefined reference to `BinaryTree<char>::BinaryTree()'

Here's the code for the header file:

#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;



template<typename Type>
class BinaryTree
{
    public:
        struct TreeNode
        {
                Type nodeinfo;
                BinaryTree<Type> *left;
                BinaryTree<Type> *right;
        };
        BinaryTree();
        void setInfo(Type a);
        void setSubtree(Type a);
        bool isEmpty();
        Type Info();
        void inOrder();
        void preOrder();
        void postOrder();
        virtual ~BinaryTree();
    protected:
        TreeNode *root;
        stack<TreeNode*> s;
        stack<TreeNode*> temp;
    private:
      void postOrder(TreeNode *r);
};


#endif  /* BINARYTREE_H */

And here's the code for its implementation:

#include "BinaryTree.h"

template <typename Type>
BinaryTree<Type>::BinaryTree(){

    root = NULL;
}

template <typename Type>
void BinaryTree<Type>::setInfo(Type a){
  root->nodeinfo = a;
  root->left = NULL;
  root->right = NULL;
  s.push(root);
}

template <typename Type>
void BinaryTree<Type>::setSubtree(Type a){
  root->nodeinfo = a;
  root->left->root = s.top();
  s.pop();
  root->right->root = s.top();
  s.pop();
  s.push(root);
}

template <typename Type>
bool BinaryTree<Type>::isEmpty(){
  return (root==NULL);
}

template <typename Type>
Type BinaryTree<Type>::Info(){
  return root->nodeinfo;
}

template <typename Type>
void BinaryTree<Type>::inOrder(){

  TreeNode *c;
  c = s.top();

  while (c!=NULL || (!temp.empty())){
    if (c!=NULL)
    {
    temp.push(c);
    c = c->left;
    }
    else{
      c = temp.top();
      temp.pop();
      cout << c->nodeinfo +" ";
      c = c->right;
    }
  }

}

template <typename Type>
void BinaryTree<Type>::postOrder(){
  postOrder(s.top());
}

template <typename Type>
void BinaryTree<Type>::postOrder(TreeNode *r){
  temp.push(s.top());
  TreeNode *c = temp.top();
  s.pop();
  postOrder(c->left->root);
  postOrder(c->right->root);
  cout << c->nodeinfo + " ";

}

template <typename Type>
void BinaryTree<Type>::preOrder(){
  TreeNode*c = s.top();
  while (c!=NULL||(!temp.empty())){
    if (c!=NULL){
      cout << c->nodeinfo + " ";
      temp.push(c);
      c=c->left;
    }
    else{
      c=temp.top();
      temp.pop();
      c=c->right;
    }
  }
}

template <typename Type>
BinaryTree<Type>::~BinaryTree(){

}

In main I call:

BinaryTree<char> tree;

and get the error. Help?

Community
  • 1
  • 1

3 Answers3

4

You have to place the implementation and declaration of your class in the same file while working with template class.

The compiler needs to generate the code at the same place where template class is used.

Dynamic Allocation in Template Class Constructor

You can do it like this.

template <typename T>
class myClass
{
   //public and private interface. 
} ;

//Here the implementation of the interface goes, just beneath the declaration.
Community
  • 1
  • 1
Coding Mash
  • 3,338
  • 5
  • 24
  • 45
  • That works! This makes me wonder why my professor said he preferred the implementation to be in a separate file though. Thanks for the help. – Brandin Jefferson Sep 24 '12 at 19:26
1

When you write a templated function like

template <typename Type>
BinaryTree<Type>::BinaryTree(){

    root = NULL;
}

the compiler doesn't actually generate the code for that function until it sees the instantiation of the template argument.

That's why there's no BinaryTree<char>::BinaryTree(); the compiler never generated the code for this! The reason is that your char instance is in a separate compilation unit (object file) from where this template function is defined.

To fix this, either place your main() function in the same file that defines all of BinaryTree's member functions, or place the member functions in the header file that declares the class.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
0

The error means that the linker has not found the definition of the constructor for that type. The main cause in templated code is that the definition of the function (contructor in this case) is not available in the place of instantiation, and no explicit instantiation was performed. The simple solution is to provide the definitions of the template in the header to make them available.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489