I am trying to create a queue which will use generic item. I am receiving an error with the following code.
How to use the template class inside another class?
Here is what I have tried so far:
#include <iostream>
using namespace std;
template<class T>
class Item
{
public:
Item(const T & item)
: itemVal(item)
{
}
private:
T itemVal;
};
class MyQueue
{
public:
// Error #1
void InsertNode(const Item & item);
private:
struct Node {
// Error #2
Item item;
struct Node * next;
};
};
int main()
{
Item<int> * element = new Item<int>(9);
return 0;
}
Item is not a type, it is a class template. You need to provide the template parameter. In this case, int:
void InsertNode(const Item<int> & item)
and
struct Node{
Item<int> item;
Node<int> * next;
};
Otherwise, you can make MyQueue and Node class templates.
It would be better to redesign your class.
template<class T>
class MyQueue {
struct Node {
T item;
Node * next;
};
public:
MyQueue();
void InsertNode(const T & item);
private:
Node * _root;
};
P.S. Sorry for my English.
Related
I have defined a struct within the protected section of a parent class, which I would like to use in an inherited class.
This works as expected if the parent/child classes aren't templated classes. But does not compile as-is below.
Specifically, the compiler (clang 8.0.1) reports:
inheritance_example.cpp:33:26: error: unknown type name 'Node'
this->head = new Node(toAdd);
From what I have read, I am guessing that the template type specification isn't being assigned to Node, and is thus not being found by the inherited class, but trying the fixes I have found in that vein (i.e. add something along the lines of using Parent<T>::Node, or add a type specifier to the call to the Node constructor), have not worked for me.
Any ideas on how to fix this issue?
#include<iostream>
template <class T>
class Parent
{
protected:
struct Node
{
Node(int value)
{
this->data = value;
this->next = nullptr;
};
~Node() {};
Node* next;
int data;
};
Node* head;
public:
Parent() {};
~Parent() {};
};
template <class T>
class Child : Parent<T>
{
public:
Child()
{
this->head = nullptr;
};
~Child()
{
delete this->head;
this->head = nullptr;
};
void dummyAdd(T toAdd) {
this->head = new Node(toAdd);
};
void dummyPrint()
{
std::cout << this->head->data << std::endl;
};
};
int main()
{
Child<int> t;
t.dummyAdd(5);
t.dummyPrint();
return 0;
}
In order to pack the comment into an answer!
Node is a depended name and hence you need to use keyword typename there. Meaning in the dummyAdd function, you need
void dummyAdd(T toAdd)
{
this->head = new typename Parent<T>::Node(toAdd);
// ^^^^^^^^^^^^^^^^^^^^
};
That is, however, a bit verbose/ more typing. Therefore providing a type alias for Node in the Child will be a good idea.
template <class T>
class Child : Parent<T>
{
using Node = typename Parent<T>::Node; // template type alias
public:
void dummyAdd(T toAdd)
{
this->head = new Node(toAdd); // now you can this
};
// other code...
};
I am trying to write a template for a class. This class uses a Node class within it so I have defined the Node class as having the List class as a friend. See below.
template <typename T>
class Node {
private:
Node() {
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList {
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node *_head;
Node *_tail;
};
I have another file where the classes are implemented. I get this error with or without the template definition above the List class. Can someone explain this?
This works for me:
template <typename T>
class Node
{
private:
Node()
{
next = nullptr;
prev = nullptr;
}
Node(int data) : Node() { this->data = data; }
Node *next;
Node *prev;
int data;
template<typename T> friend class DoubleLinkedList;
};
template<typename T>
class DoubleLinkedList
{
public:
DoubleLinkedList();
~DoubleLinkedList();
private:
Node<T> *_head;
Node<T> *_tail;
};
Consider the following class definitions ...
Node
template <class T> class Node {
private :
T* data;
Node<T>* next;
public :
Node(T* data);
void setData(T* data);
T* getData();
void setNext(Node<T>* next);
Node<T>* getNext();
};
Linked List
template <class T> class LinkedList {
private :
Node<T>* start;
public :
LinkedList();
void add(Node<T>* node);
bool isEmpty();
};
Main
#include "Foo.h"
int main() {
Foo foo();
Node<Foo> node(&foo);
LinkedList<Foo> linkedList();
linkedList.add(&node);
return 0;
}
When it is compiled it throws the following error...
Request for member 'add' in 'linkedList', which is of non-class type 'LinkedList<Foo>()'
I am quite inexperienced making use of templates, so any help would be greatly appreciated.
Foo foo(); and LinkedList<Foo> linkedList(); are not variables but are function prototypes.
Please use Foo foo; and LinkedList<Foo> linkedList; instead.
You can also use Foo foo = Foo(); and LinkedList<Foo> linkedList = LinkedList<Foo>(); to make it clear that the constructors are called.
So I'm trying to work out how inheritance works when templates are in the mix. Most compilers really don't seem to have this figured out yet, so I'm having a little syntax difficulty. All the weird includes in SkipNode.h are from trying to get eclipse to stop yelling at me. I'm getting a syntax error when trying to declare the constructor in SkipNode.h, so any help here would be useful.
Here is node.h
#ifndef NODE_H_
#define NODE_H_
template<class T>
class Node
{
public:
Node(Node<T>* next, Node<T>* prev, T item);
virtual ~Node();
Node* getPrev() { return prev;};
Node* getNext() { return next;};
Node* getItem() { return item;};
void setItem(T item){Node<T>::item = item;};
void setNext(Node* next){Node<T>::next = next;};
void setPrev(Node* prev){Node<T>::prev = prev;};
private:
Node* next;
Node* prev;
T item;
};
Here is SkipNode.h, where skipnode inherits from Node.
#include "Node.h"
#include "Node.cpp"
#include "SkipNode.h"
#include "SkipNode.cpp"
template <class T>
class SkipNode: public Node
{
public:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item) : Node(next, prev, item);
virtual ~SkipNode();
Node* getChild(){return child;};
void setChild(Node* child){SkipNode::child = child;};
private:
Node *child;
};
#endif /* SKIPNODE_H_ */
Node is a template, you should pass in template parameter
template <class T>
class SkipNode: public Node<T>
// ^^^
Also you need to provide SkipNode constructor definition as you have provided member iniatilizer list.
update:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item)
: Node(next, prev, item);
To:
SkipNode(Node<T>* next, Node<T>* prev, Node<T>* child, T item)
: Node(next, prev, item)
{
}
You're missing an #endif in node.h and you need to provide the template parameter to your base class:
template <class T>
class SkipNode : public Node< T >
....
This level of indirection exists to allow inheritance from a template class by a class that has different (or zero) template parameters. For instance:
class Foo : public Node< int >
I have a tree_node class and a tree class.
template<typename T>
class tree_node
{
public:
tree_node(const std::string& key_, const T& value_)
: key(key_), value(value_)
{
}
private:
T value;
std::string key;
};
template<typename T>
class tree
{
public:
tree() : root(new tree_node<T>("", ???)) { }
private:
tree_node<T>* root;
};
tree_node expects an instance of T when creating. How can I pass it in the ??? place? I can say T(), but it will work only if T has a parameterless constructor. I can't have a parameterless constructor for tree_node as it won't compile if T doesn't have a parameterless constructor.
I am looking for a way to design tree_node which can hold all types correctly including pointer types.
Edit
After trying various methods, I found that boost::optional is helpful in this case. I can make the T value into boost::optional<T> value. This will solve the empty constructor issue. So I can have another constructor overload of tree_node which just takes a key. This can be used by the root node. Is this the correct way to go?
Thanks..
Init root value should be zero. If you push new node you obviously know value.
template<typename T>
class tree
{
public:
tree() : root(0) { }
void push (const std::string& key, const T & t) {
if (root == 0) {
root = new tree_node<T>(key, t);
} else {
// Make complex tree
}
}
private:
tree_node<T>* root;
};
Add
If you use suffix tree you should make two types of vertices:
enum NodeType { EMPTY_NODE, VALUE_NODE };
class base_tree_node
{
public:
base_tree_node() :parent(0), left(0), right(0) {}
virtual NodeType gettype() = 0;
protected:
base_tree_node* parent;
base_tree_node* left;
base_tree_node* right;
};
class empty_tree_node : base_tree_node
{
virtual NodeType gettype() { return EMPTY_NODE; }
}
template<typename T>
class tree_node : base_tree_node
{
public:
tree_node(const std::string& key_, const T& value_)
: key(key_), value(value_)
{
}
virtual NodeType gettype() { return VALUE_NODE; }
private:
T value;
std::string key;
};
tree( const T & t ) : root(new tree_node<T>("", t )) { }
I have once done a linked list (just for fun) which needed a sentinel node not meant to hold any data, and I had the following structure:
struct BaseNode
{
BaseNode* next;
BaseNode(BaseNode* next): next(next) {}
};
template <class T>
struct Node: public BaseNode
{
T data;
Node(const T& data, BaseNode* next): BaseNode(next), data(data) {}
};
template <class T>
struct List
{
BaseNode* head;
List(): head(new BaseNode(0)) {}
void add(const T& value)
{
Node<T>* new_node = new Node<T>(value, head->next);
head->next = new_node;
}
T& get_first()
{
assert(head->next);
return static_cast<Node<T>*>(head->next)->data;
}
//...
};
The class itself must make sure it gets necessary casts right and doesn't try to cast head or root itself to Node<T>.
A tree node should have (or be) a collection of child nodes. A tree should have (or be) a collection of root nodes. Both those collections should be the same type. Very simply:
template <class T>
class NodeCollection
{
std::vector<Node<T> *> nodes;
public:
// any operations on collection of nodes
// copy ctor and destructor a must!
};
template <class T>
class Node : public NodeCollection<T>
{
T value;
public:
// ctor
// access to value
};
template <class T>
class Tree : public NodeCollection<T>
{
public:
// ctor
};
This way the shared definition of Tree and Node is actually in NodeCollection, and so Tree doesn't need to carry a dummy value.