The template declaration is:
template <typename DataType>
class BST
and the error that I keep getting is
bst.h(101) : see reference to class template instantiation 'BST::BinNode' being compiled
bst.h(183) : see reference to class template instantiation 'BST' being compiled
I think my syntax may be wrong, but I'm not sure what about it is. Could somebody push me into the right direction. I just cannot get it to compile. Class BinNode is a private class of the main class BST. The line the error is referring too is DataType BinNode::treeheight(BinNode * p)
private:
/***** Node class *****/
class BinNode
{
public:
DataType data;
BinNode * left;
BinNode * right;
DataType treeheight(BinNode * p);
template <typename DataType>
DataType BinNode::treeheight(BinNode * p)
{
if(p != 0)
{
int heightl = treeheight(p->left);
int heightr = treeheight(p->right);
}
if(heightl > heightr)
return heightl;
else
return height r;
}
When defining the member function (outside the class, that is), you need to qualify the member function definition as Node<DataType>::BinNode::treeheight(…) {…} since BinNode is a nested class of Node.
Related
I'm having a gigantic trouble with inheritance. I have a normal node as follows (please, ignore any typo in the code, I do not have it right now, but it compiles fine)
template<typename T>
class Node {
Node<T> *parent, *left, *right;
...//simple methods
}
then, I implement a normal BST using the node I just created:
template<typename T>
class tree {
virtual Node<T>* insert(T value);
...// other methods of tree
}
now I want to make a red black tree, but the code for it is almost the same, so I just try to override, say, insert:
template<typename T>
class rb_node : public node<T> {
int color;
...//methods to retrieve and set the color as well the constructor
}
template<typename T>
class rb_tree : public tree<T> {
Node<T> *insert(T value){
auto z = (rb_node<T>*)tree<T>::insert(value);
while(z->parent()->color() == RED)...
}
since I cast, the z->parent() is recognized as a rb_node, but the parent don't since it was constructed in the base class, so it does not have the color() method. How do I solve this problem that is killing me for almost two weeks??
Obs: if anyone need, my code is at https://github.com/dodonut/Algorithms/tree/master/Data_Structures.
I tried to override the variables of node to rb_node on constructor(but cannot cast nullptr), on the method inside rb_node to return rb_node(but the signature of base class methods is different)
One possible solution might be to have the base tree class also take an optional NodeType template argument? As in
template<typename T, typename NodeT = Node<T>>
class tree
{
...
virtual NodeT* insert(T const& value);
...
};
Then the sub-class could use its special rb_node:
template<typename T>
class rb_tree : public tree<T, rb_node<T>>
{
...
rb_node<T>* insert(T const& value) override;
...
};
I am implementing a binary tree class that is almost identical to this one. However, in my task, the node struct must be a templated structure. Therefore I changed struct node to:
template <typename T>
class node {
public:
T data;
node<T> *left, *right;
}
so far so good, until I added a node instance to btree as a member variable:
class btree {
// ......
private:
template <typename T>
node<T> *root = NULL; // error
}
error message says
C3857: multiple template parameter lists are not allowed.
I tried to move root = NULL to btree's default constructor, does not work either.
You cannot have a templated variable declaration. There would be no way to specify the type to use for the variable. You can either make btree a template and use that type for the node
template<typename T>
class btree {
// ......
private:
node<T> *root = NULL; // error
}
or specify what type of node you want in btree
class btree {
// ......
private:
node<some_type> *root = NULL; // error
}
I'm not sure that there is allowed to ask questions like this. But I can't really understand the code which should be used in my program.
The situations is that I have to apply an earlier written class, which is design by some pattern and I have no right to change it. Unfortunately I don't know which patter it is, and neither how to use it.
(The story is about a linked list template.)
The code is something like this:
template<typename T> class LListNode {
public:
LListNode();
void setNext(T*);
...
T* next() const;
};
template<typename T> inline void LListNode<T>::setNext(T* next) {
static_cast<T*>(this)->m_next = next;
}
...
This was the node class, the next is the main list class:
template<typename T> class LList {
public:
LList();
bool isEmpty() const;
...
T* head() const;
...
void push(T*);
...
private:
T* m_head;
T* m_tail;
};
First, I tried to instantiate just the LList class with my own class as template class. But it didn't worked. Than I thought that maybe my own class (which will be stored in the List) should be inherited from the LListNode class. Thats seemed to be a good idea, but then there I got stuck.
How can I define a class which is inherited from another class, which gets the currently defined class as template parameter?
Just to make it clear:
class Foo : LListNode<Foo> {
private:
Foo* m_next;
public:
...
At this point my compiler (gcc (Ubuntu/Linaro 4.6.4-1ubuntu1~12.04) 4.6.4
) is crying:
In instantiation of 'void LListNode<T>::setPrev(T*) [with T = Foo]':
required from LListNode<T>::LListNode() [with T = Foo]'
Foo.h: required from here
LList.h: error: LListNode<Foo>' is an inaccessible base of 'Foo'
You forgot public :
class Foo : public LListNode<Foo> {
private:
Foo* m_next;
public:
...
I need to change the first line to : template <class T> class Node{
class Node {
private:
double data;
Node* next;
public:
Node(double);
virtual ~Node(); //for later use of polymorphismi, review the topic again
friend class Stack; // allows dStack for private member access
};
Node::Node(double data) {
this->data = data;
next = 0;
}
Node::~Node() {
}
but i am unsure of all the internal work i need to change. Do i just need to change the private data member and the public Node function?
I think what you are looking for is something along the lines of the following:
template<typename T>
class Node
{
private:
T data;
Node* next;
public:
Node(const T& d);
virtual ~Node();
// ... etc
};
Note that you will either need to implement the template class inline, in the same file, or include the implementation at the bottom of the header file.
The point is that you change your class so that it can be used for other types except double, for example int, float etc in the same way. If we think of it in more abstractly, you need to use the class for objects of type T, where T can be any of the types mentioned above (or even more).
So, in general, you need to put template <class T> (Setting it as a template class) before your class and replace double with T type.
for class declaration:
template<typename T>
class Node
for class functions implementation:
template<typename T>
Node<T>::Node()
I'm making a simple boost::any-like class for educational purposes, but I can't figure out how to access the stored value. I can set the value perfectly, but when I try to access any member in the "holder" class the compiler just complains that the member wasn't found in the class it was derived from. I can't declare the members as virtual because of the templates.
Here's the relevant code:
class Element
{
struct ValueStorageBase
{
};
template <typename Datatype>
struct ValueStorage: public ValueStorageBase
{
Datatype Value;
ValueStorage(Datatype InitialValue)
{
Value = InitialValue;
}
};
ValueStorageBase* StoredValue;
public:
template <typename Datatype>
Element(Datatype InitialValue)
{
StoredValue = new ValueStorage<Datatype>(InitialValue);
}
template <typename Datatype>
Datatype Get()
{
return StoredValue->Value; // Error: "struct Element::ValueStorageBase" has no member named "Value."
}
};
It's fine to add virtual functions to templates- just the functions themselves cannot be templates. A templated class or struct can still have virtual functions just fine. You need to use the magic of dynamic_cast.
class Element
{
struct ValueStorageBase
{
virtual ~ValueStorageBase() {}
};
template <typename Datatype>
struct ValueStorage: public ValueStorageBase
{
Datatype Value;
ValueStorage(Datatype InitialValue)
{
Value = InitialValue;
}
};
ValueStorageBase* StoredValue;
public:
template <typename Datatype>
Element(Datatype InitialValue)
{
StoredValue = new ValueStorage<Datatype>(InitialValue);
}
template <typename Datatype>
Datatype Get()
{
if(ValueStorage<DataType>* ptr = dynamic_cast<ValueStorage<DataType>*>(StoredValue)) {
return ptr->Value;
else
throw std::runtime_error("Incorrect type!"); // Error: "struct Element::ValueStorageBase" has no member named "Value."
}
};
If you change Get to return a Datatype* you can return NULL instead of throwing. You also haven't handled the memory of the previous value of StoredValue, but I'm leaving that up to you.
You need to cast it to ValueStorage first.
Also add virtual destructur to ValueStorageBase class, to have polymorphic class. Without it you can't runtime check if your casting is OK :).
After it you can write:
template <typename Datatype>
Datatype Element_cast()
{
//throw exception for a wrong cast
if(typeid(*StoredValue)!=typeid(ValueStorage<Datatype>) )
throw exception;
//we already checked, that our type casting is OK,
//So no need for dynamic_cast anymore
return static_cast<ValueStorage*> (StoredValue)->value;
}