MichaelMitchell
MichaelMitchell

Reputation: 1167

C++ Generic node class will not take nodes of different type

I am trying to make a generic node class that can store references to other generic nodes that can have different types for their data.

template < class T >
class BiTreeNode {
    T d;
    BiTreeNode *parent; //Trying to store a node of different type here
public:
    BiTreeNode(void);
    BiTreeNode(T);
    void setData(T);
    T * getData(void);
    void setParent(BiTreeNode * const); // Error here.
    BiTreeNode * getParent(void);
};

Specific Error:

Error 1 error C2664: 'void BiTreeNode<char>::setParent(BiTreeNode<char> *const )' : cannot convert argument 1 from 'BiTreeNode<int> *' to 'BiTreeNode<char> *const ' (File Location) 42 1 P=NP

Upvotes: 0

Views: 1108

Answers (2)

Yochai Timmer
Yochai Timmer

Reputation: 49221

Different template instantiations, even if it seems that they have the same name, are not related.

Templates are designed for code reuse, every template instantiation with a different type is actually a totally different class type with no polymorphic relation.

A BiTreeNode<int> and BiTreeNode<char> are 2 different classes with no common base class. It's easy to remember this if you just read the <> signs as part of the class name.

To do what you're trying to achieve there, just have the templated class derive from a common base class:

class BaseTreeNode
{
};

template < class T >
class BiTreeNode : public BaseTreeNode
{
 T d;
    BaseTreeNode *parent; 

...

}

This way every templated class that is created derives from the same class, and you have the polymorphism you need.

Upvotes: 1

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275270

A template is a class factory: it generates classes (not values: classes). The resulting classes have very little conection (you can do type pattern matching on them is all).

The template generates types.

The types generate values.

You cannot take a pointer to one type of value and point it to a different type of value, other that what the rules on common layout/inheritance allow. And that is what you are asking to do.

Now you can create some kinds of relationship between the generated types, but inheritance is rarely what you want in practice, and common layout does not give you what you want either. Having a common parent is sometimes useful, and would give you some of what you want.

As for your syntax error, the name of a template class within the template class itself without an argument list refers implicitly to the template class with the 'same' template arguments. So within foo<int>, foo refers to foo<int> implicitly.

It is possible you are trying to replicate a technique used with generics in C++: generics are not templates. Templates can be used to generate generics, but the process is convoluted enough that you are better off writing template code that does template stuff, not generic stuff. Ie, redesign.

The common parent means you create a base class that the template class generated inheits from. Use base* to refer to a pointer to any value of any type generated by your template. Stick properties common to every type of class generated by your template in it (like a parent base pointer), so you can access them via base* pointers.

If you want access to properties that are not common (like T get_value()), the above does not help you. Figure out how to solve the problem with a 3-class case (int double and base say), and see if the technique works for the n+1 class case. There are enough complications that I could not guess from the above description what the answer is: write a new question if you have such properties.

Upvotes: 0

Related Questions