Call child method from parent, when child is a template - c++

I have this college project where I have to create a BinarySearchTree class using templates. We have to read a file and create the tree depending of the data type in the file. I made a parent class for the tree called BST so I can use the tree without giving it a class type.
class BST{
public:
BST();
~BST();
}
And the tree
template <class T> class BinarySearchTree : public BST{
public:
void add(T val);
}
And I wanted to do this:
BST tree = BinarySearchTree<int>(); //just an example, it can be of any type
tree.add(5); //doesn't work
How can I call "add" from BST without giving a specific variable type?

You have to make a virtual method in the class BST and also make BST a template.
virtual void add(T val) = 0;

Use CRTP(Curiously Reccursive/Reccuring Template Pattern) and Concept Pattern.
https://qiita.com/Riyaaaa_a/items/a9af401520f238f45b80
This is written in Japanese, however, it's interesting!

Related

Inheriting from a class but using a subclass of an attribute

I have to implement a Red/Black tree (RBTree) in C++, inheriting from a Binary Search Tree (BSTree) class I already created.
The BSTree class contains a Node pointer (Node is a class I created for BSTree) to the tree root.
I want to create a Node subclass called "RBTNode", which contains color attribute and related methods (so RBTNode is subclass of Node), then I want to create the RBTree class inheriting from BSTree, but with the new RBTNode instead of the standard Node.
The structure would be as follows:
BSTree contains Node;
RBTNode is subclass of Node;
RBTree is subclass of BSTree;
RBTree contains RBTNode;
How could I achieve that?
As suggested by Jarod42 in the comments, you can achieve this by making the node type a template parameter for the BSTree class.
Say you have these two node classes:
template<typename KeyT>
class BSNode {
public:
KeyT key;
// ...
};
template<typename KeyT>
class RBNode : public BSNode<KeyT> {
public:
bool color;
};
Then you could add a node type template parameter to BSTree and make it BSNode by default. You can then use RBNode while inheriting in RBTree.
template <typename KeyT, typename NodeT = BSNode<KeyT>>
class BSTree {
protected:
NodeT *root;
};
template <typename KeyT>
class RBTree : public BSTree<KeyT, RBNode<KeyT>> {
// root will be of type RBNode<KeyT>* here
};

How to inherit a red black tree from a normal bst

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;
...
};

Does this class setup violate the Liskov Substitution Principle

I have this piece of code for a Tree. The BSTnodes contain the actual data. BST is a wrapper around them by inheriting from unique_ptr<BSTnode<Key,Data>>. BST doesn't add any new fields to the class.
The inheritance makes it so that my tree is a unique_ptr<BSTnode>, but is that a correct way of implementing it? The added operations for the BST like rotate() / insert() or remove() are specific to the data structure. You wouldn't and shouldn't expect them for a regular unique_ptr, but this does mean that a BST can't be used interchangeably with a unique_ptr.
If this implementation strategy is incorrect, how should I solve it?
template <class Key, class Data>
class BST : public unique_ptr<BSTnode<Key, Data>>
{
using unique_ptr<BSTnode<Key, Data>>::unique_ptr;
// operations ...
};
template <class Key, class Data>
class BSTnode
{
friend class BST<Key, Data>;
public:
//constructors ...
protected:
Key key;
Data data;
BSTnode<Key, Data> *parent;
BST<Key, Data> left, right;
};
LSP aside, inheriting standard classes is generally problematic and not a recommended solution for most cases. In this case, as #SomeProgrammerDude suggests, it's better to use composition and put the pointer inside your class:
template <class Key, class Data>
class BST
{
std::unique_ptr<BSTnode<Key, Data>> root;
// operations ...
};
Noone would want to use your BST class to replace the unique_ptr anyway. It's a separate data container that just happens to utilize unique_ptr to store its data.

Container implementation using templates and inheritance

I'm trying to implement a generic ranked tree container by inheriting a basic 2-3 tree container
basic tree is declared as follows :
template<typename T>
class Node{
// etc..
}
template<typename T>
class Tree{
Node* root;
// etc
}
and suppose i wanted to implement a tree of integers, i though i could declare a class as follows :
class RankedNode : public Node<int>{
// ...
}
class RankedTree : public Tree<int>{
RankedNode root*; // for example
// ...
}
The class RankedNode will include additional fields to the class Node, that aid in fast traversal of the tree ( O(log n) ) , and by using inheritance i'll be able to prevent code duplication.
However, i don't know how to go about doing so correctly, any ideas would be appreciated :)
You could start by making Tree a template on N, (the node type), instead of T (the value type):
template<typename T>
class Node{
// etc..
}
template<typename N>
class Tree{
N* root;
// etc
}
This way you could write
class RankedNode : public Node<int>{
// ...
}
class RankedTree : public Tree<RankedNode>{
// RankedNode* root; <- remove this; it is already in Tree<RankedNode>
// ...
}
and add only fields that are really new compared to base classes.

C++ Defining a specific object type when extending a template class

I have written a short template list class defining some methods I would like to use in implementations of it. My current problem is that I am having trouble extending the generic template type and defining a specific type.
In other words, assume I have a class called MyType
List.h:
template<class T>
class List
{
public:
Node<T> *head;
Node<T> *tail;
...
}
Inside the Node class:
public:
virtual T getData();
I want to extend this class with a specific defined type MyType so that I can have getData() behave differently in the extended class MyTypeList. I am having trouble with syntax. Any help would be greatly appreciated!
class MyTypeList : public List<T>
{
...
}
You can do something like this:
struct MyTypeList : List<MyType> {
};
although it is about the same as doing:
typedef List<MyType> MyTypeList;