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()
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;
...
};
How to get rid of abstract classes in the given implementation of self-referencing templates?
I just tried to implement a skip-list data structure.
So I wanted to create the template Node such that I may instantiate the class of the next link for different node classes to avoid class casts.
Have found these questions:
Self-referencing Template in Template Argument
How to properly declare a self-referencing template type?
but none of them have a solution. Then I've made my own solution based on two lines of inheritance. One is the sequence of "abstract" templates (for Next argument propogation). Another is to instantiate concrete classes. But feel like it can be improved to handle the same without redundant abstract templates (NodeAbstract, NodeWithKeyAbstract etc). After several own tries I want to ask you help me:
template <class Value, class Next >
class NodeAbstract
{
public:
Value m_value;
Next * next;
NodeAbstract () : next(0) {}
Next * getNext() {return next;}
};
template <class Value, class Key, class Next >
class NodeWithKeyAbstract : public NodeAbstract <Value, Next >
{
public:
Key m_key;
};
template <class Value, class Key>
class NodeWithKey : public NodeWithKeyAbstract <Value, Key, NodeWithKey<Value,Key> >
{
};
template <class Value, class Key, int maxlevel, class Next>
class NodeSkipListAbstract : public NodeWithKeyAbstract<Value, Key, Next >
{
public:
Next * nextjump[maxlevel-1];
};
template <class Value, class Key, int maxlevel>
class NodeSkipList : public NodeSkipListAbstract<Value, Key, maxlevel, NodeSkipList<Value, Key, maxlevel> >
{
};
If I understand you correctly, your problem is basically that different maxlevel values in would produce different classes, and so you couldn't use one array to store them all (correct me if I'm wrong).
You cannot fully get rid of abstract classes - if you want to have nodes with different max level as different classes (different template specializations) you have to provide some common denominator for them.
Good news is that you can get rid of Curiously Recurring Template Pattern instead - since you use pointers you don't have to refer to exact implementation type (e.g. knowing exact template specialization) if you're abstraction gives you access to all information you need. Also your code can be simplified a bit.
Consider this code:
template <class Key, class Value>
class Node {
public:
virtual ~Node() = default;
virtual std::size_t MaxLevel() const = 0;
virtual Node* Skip(size_t level) const = 0;
// add setter as well
Key key;
Value value;
};
template <class Key, class Value, std::size_t max_level>
class NodeImpl : public Node<Key, Value> {
public:
typedef Node<Key, Value> node_type;
NodeImpl() : skips() {}
size_t MaxLevel() const { return max_level; }
node_type* Skip(std::size_t level) const {
return level < max_level ? skips[level] : nullptr;
}
// add setter as well
private:
node_type* skips[max_level];
};
template <class Key, class Value>
class SkipList {
public:
typedef Node<Key, Value> node_type;
node_type* head;
};
Here Node provides you with an abstraction for a "skipping" behavior. NodeImpl would be used to generate Nodes with different max level, but in the end used implementation would be transparent to you - you would only use Node's interface. Also on syntax level you would only use Node* type, so variety of implementations wouldn't be a problem. Virtual destructor would ensure that delete frees all memory, and key and value would always be accessible as public fields.
This code can of course be improved. Raw array can be replaced by std::array. Whole idea of max_level as a template can be get rid of if you decide to use std::vector with size set in constructor instead of array (then you'll only have Node and SkipList). As a bonus creating new nodes would be easier, since now you'd have to write some factory with specializations of all NodeImpl's from 1 to some value. Additionally pointers could be replaced by some smart pointer to avoid memory leaks.
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'm making a template library in c++. I think it needs to be in the form of a template class because it has to be able to store some data. I would like to be able to create an instance of that class without having to specify a data type.
Here's what the class template would look like
template<class T>
class MyTemplateClass{
public:
void saveData(T data);
private:
T my_data;
};
template<class T>
void MyTemplateClass<T>::saveData(T data){
//bunch of code goes here
}
and here's how I would like to declare it:
class LibraryUser{
public:
void saveDoubleData(double data);
void saveFloatData(float data);
private:
MyTemplateClass<UNKNOWN_TYPE> my_generic_object;
};
and use it:
void LibraryUser::saveDoubleData(double data){
my_generic_object.saveData(data);
}
void LibraryUser::saveFloatData(float data){
my_generic_object.saveData(data);
}
What should UNKNOWN_TYPE be? Is this possible?
EXTRA NOTES: I cannot edit the function prototypes of the LibraryUser class because it is part of an existing plug-in framework. I'd rather not use template specialization because I don't want to double the code in saveData() since it's actually pretty long.
You should make the LibraryUser class a template as well:
template<class T>
class LibraryUser{
public:
void saveData(T data);
private:
MyTemplateClass<T> my_generic_object;
};
Alternatively, you can use boost::any if the type is really unknown, or boost::variant if the type is in a specified set of types.
The template classes are actually different from each other so you can't really change the template type runtime without using some trick. If you don't want to make LibraryUser also a template, you can store multiple variables. In this case, if you want to save yourself the trouble of duplicating every code, but you have a limited number of different types just use multiple variables and store which one is actually used. Not really nice, but saves you from making more template classes.
class LibraryUser{
public:
void saveIntData(int data);
void saveFloatData(float data);
private:
MyTemplateClass<int> my_int;
MyTemplateClass<float> my_float;
};
Use it:
void LibraryUser::saveFloatData(float data){
my_float.saveData(data);
}
void LibraryUser::saveIntData(int data){
my_int.saveData(data);
}
Instead of having a class member, why not use local instances of your template class?
void LibraryUser::saveIntData(float data){
MyTemplateClass<float> saver;
saver.saveData(data);
}
void LibraryUser::saveFloatData(int data){
MyTemplateClass<int> saver;
saver.saveData(data);
}
If MyTemplateClass needs s.th. you want to have initialized once (e.g. a database connection), make a class member for that one separately (in LibraryUser) and pass a reference to the constructor of MyTemplateClass:
template<class T>
class MyTemplateClass{
public:
MyTemplateClass(DBConnection& conn);
void saveData(T data);
private:
T my_data;
DBConnection& my_conn;
};
class LibraryUser{
public:
void saveIntData(int data);
void saveFloatData(float data);
private:
DBConnection my_conn;
};
void LibraryUser::saveIntData(float data){
MyTemplateClass<float> saver(my_conn);
saver.saveData(data);
}
About your EXTRA NOTES:
It is also safe to assume that a given OtherClass object will consistently only call either saveFloatData or saveIntData, not both.
IMHO that's a bad assumption (restriction) made for client usage, if you're going to design a framework.
UPDATE:
Another option I can think of, is to just templating the function in question, not the whole class:
class MyGenericClass{
public:
MyGenericClass();
template<class T>
void saveData(T data);
};
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;