7

I'm having trouble creating a class object from a template class in which I need the constructor to also be a template and accept a parameter when the object is created. However, when I attempt to create the object, I receive an error message stating that I'm referencing something that doesn't exist.

Here's my code:

using namespace std;
#include <cstdlib>

template <class Node_Type>
class BinaryTree 
{
public:
    BinaryTree(Node_Type);
    BinaryTree(Node_Type, Node_Type);
    BinaryTree(Node_Type, Node_Type, Node_Type);
    bool isEmpty();
    Node_Type info();
    Node_Type inOrder();
    Node_Type preOrder();
    Node_Type postOrder();


private:
    struct Tree_Node
{
    Node_Type Node_Info;
    BinaryTree<Node_Type> *left;
    BinaryTree<Node_Type> *right;
};

Tree_Node *root;

};

#endif

and my .cpp:

template <class Node_Type>
BinaryTree<Node_Type>::BinaryTree(Node_Type rootNode) {

    root = rootNode;
    root->left = NULL;
    root->right = NULL;

}

There's more to the .cpp, but it's just other function members that are irrelevant. My constructor shown above is what I can't get to work.

In my main, I'm attempting to declare my object with the call:

BinaryTree<char> node('a');

but when I try this, I get an error message stating:

undefined reference to `BinaryTree<char>::BinaryTree(char)'

I've been trying to figure this out for two days now. I've Googled every topic I can think of and read countless examples on Stack Overflow and other sources with no help. Can anyone please explain what my problem is? I know how to do my project, and I'd be finished by now if the syntax wasn't so ridiculous in C++. Thanks in advance!

9
  • 1
    The answer to your problem is exactly what the compiler is telling you. a Tree_Node* is not a char. Commented Sep 18, 2013 at 19:38
  • 1
    Short and imprecise: Because you have the body of your function that depends on the template inside of the .cpp file. It needs to be with your .h file either directly within your class definition or if you don't like to place it there because of to keep it easieer to read, declare the function as inline and move it outside the class definition, either in the same file or into a .hpp which you include in the .h Commented Sep 18, 2013 at 19:38
  • @WhozCraig is right root is of type Tree_Node* not char Commented Sep 18, 2013 at 19:40
  • 1
    @StephenFish that isn't right either, but ok. Its your funeral. Your root pointer and your tree node left and right pointers are all uninitialized. Commented Sep 18, 2013 at 19:48
  • 1
    @t.niese it certainly is. the error I saw was a completely different one (and oddly, the OP's compiler apparently is letting it through, whereas mine... is exhibiting exactly what you described. When he responded "I changed 'root = rootNode' to 'root->Node_Info = rootNode' and it works just fine now." I cringed. Step out of one undefined behavior, and smack into a different one. Commented Sep 18, 2013 at 19:54

3 Answers 3

10

Template code should be visible at the time of instantiation, meaning that the definition of the functions must also be in the header.

Sign up to request clarification or add additional context in comments.

Comments

6

Solution: You can't separate template implementations from the header file. Simply don't use a cpp file and put the definition in your header file (.h file).

Why? This is because cpp files can become precompiled sources, while templates are compile-time objects; therefore, the compiler cannot decide what type to use unless specified. So just put all your template undefined implementations in your header .h file.

3 Comments

While this is a correct statement, is covered extensively in this question, and would ultimately be a problem regardless, it is not the answer to the OP's question concerning the specific error message being received.
@WhozCraig Are you sure? The error message seems to be complaining that the constructor is not defined, not that the constructor is ill defined.
@AlanStokes Actually, its both, but you are correct, and I'll send Samer an upvote accordingly (in fact all three of them). The OP's code is going to have to morph extensively regardless before it is finally functional. Thanks for pointing it out. I misread the original error message.
2

You can force the instantiation of the template in another cpp file.

BinaryTree<char>;
BinaryTree<int>;
BinaryTree<double>;

That way all the functions do not need to be in header files. Some people use the extension .inl for the files with the template implementations. So the .inl file is only needed when the instantiation doesn't already exist.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.