I have the following implementation for the node class:
template<class T> class binTree; // forward declaration
template<class T> class Node {
friend class binTree<T>; // class binTree is friend
public:
//default constructor
Node(const T& d = T(), Node<T> *l = NULL, Node<T> *r = NULL) : data(d),
left(l), right(r) {};
private:
T data;
Node<T> *left, *right;
};
I'm trying to define a new node a the root of my tree, but I keep getting compilation errors...
template<class T>
void binTree<T>::insert(Node<T>*& n, const T& d){
if(n == NULL)
root = Node<T>(d);
}
I'm confused by the const T& d = T() parameter.
I think you just need to declare the binTree class and its members before you try to define the member. The following code compiles for me:
#include <cstdlib>
template<class T> class binTree; // forward declaration
template<class T> class Node {
friend class binTree<T>; // class binTree is friend
public:
//default constructor
Node(const T& d = T(), Node<T> *l = NULL, Node<T> *r = NULL) : data(d),
left(l), right(r) {};
private:
T data;
Node<T> *left, *right;
};
template <class T> class binTree
{
public:
binTree() { }
void insert(Node<T>*& n, const T& d);
private:
Node<T> root;
};
template<class T>
void binTree<T>::insert(Node<T>*& n, const T& d){
if(n == NULL)
root = Node<T>(d);
}
int main(int argc, char **argv)
{
Node<int>* nt;
binTree<int> btree;
btree.insert(nt, 4);
}
Having said this, your concept of the data structure seems messed up. Why does the insert routine in binTree require a node argument?
I'm not quite sure why you have that default override for the d variable in your default constructor. In my implementation of a Node for my Tree class, I had no default assignment. I think the issue is T(). I would recommend not trying to do that default assignment in the params listing, but instead do it in the BMI List. So it would look kind of like "data(new T), left(NULL), right(NULL)"
Additionally I would say I'm not quite certain as to why you are using T(). If that doesn't work, please post the error code so that we can have a better understanding of what is going on.
Related
I get an initialization error for a TreeNode class constructor… This is the function:
TreeNode* a = new TreeNodens; Is the issue here, not sure what I have to add to TreeNode but it needs some type of tweak!
template <typename T>
void ScapegoatST<T>::rebuild(TreeNode<T>* node){
int ns = getHeight(node);
TreeNode<T>* p = node->getParent();
TreeNode<T>* a = new TreeNode<T>[ns]();
TreeNode<T>* r;
packintoArray(node,a,0);
if (p == NULL){
r = buildBalanced(a,0,ns);
r->setParent(NULL);
} else if (p->getRight() == node){
TreeNode<T>* Tr = buildBalanced(a, 0, ns);
p->setRight(Tr);
p->getRight()->setParent(p);
} else {
p->setLeft(buildBalanced(a,0,ns));
p->getLeft()->setParent(p);
}
}
Here is the TreeNode.h:
#ifndef TREE_NODE_H
#define TREE_NODE_H
#include <cstdlib>
#include <iostream>
using namespace std;
template <typename T>
class TreeNode{
public:
TreeNode(T nData);
virtual ~TreeNode();
T getData();
TreeNode<T>* getLeft();
TreeNode<T>* getRight();
TreeNode<T>* getParent();
void setData(T nData);
void setLeft(TreeNode<T>* nleft){left=nleft;};
void setRight(TreeNode<T>* nright){right=nright;};
void setParent(TreeNode<T>* nparent){parent=nparent;};
template <typename S>
friend class ScapegoatST;
private:
T data;
TreeNode<T>* left;
TreeNode<T>* right;
TreeNode<T>* parent;
};
template <typename T>
TreeNode<T>::TreeNode(T nData){
data = nData;
left = NULL;
right = NULL;
}
template <typename T>
TreeNode<T>::~TreeNode(){
delete left;
delete right;
delete parent;
data = NULL;
}
template <typename T>
T TreeNode<T>::getData(){
return data;
}
template <typename T>
void TreeNode<T>::setData(T nData){
data = nData;
}
#endif
I tired creating a constructor for the array initialization but it wasn’t successful.
The issue here is that you've created the constructor TreeNode(T nData), which prevents the constructor with no arguments TreeNode() from being generated, but you call that constructor when you do new TreeNode<T>[ns]().
One solution would be to add a constructor TreeNode(), with a body like so:
template<typename T>
TreeNode<T>::TreeNode() {
left = NULL;
right = NULL;
}
This will mean that constructing a TreeNode with no nData will result in the node's data field being default-initialized (for primitive types, it will contain an undefined value, and for classes it will act like T() was called to construct the data value).
I implemented a linked-list called Node that had a function called freeData where it would perform a delete on the node given and any following nodes.
I wanted to implement it inside my own custom list class as a private member, but came up with this error in Visual Studio 2019:
C2672 'freeData': no matching overloaded function found
C2783 'void custom::freeData(list::Node*&): could not deduce template argument for 'T'
I don't know what to change for my freeData function header to accept a Node* as an argument. I pass the argument pHead in these functions: ~list() and clear().
The previous definition before embedding freeData into the list class was void freeData(Node <T>* &pHead).
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list() : numElements(0), pHead(NULL), pTail(NULL) { }
~list() { freeData(pHead); }
void clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
private:
struct Node;
Node* pHead;
Node* pTail;
int numElements;
};
template <class T>
struct list <T> :: Node
{
Node() : pNext(NULL), pPrev(NULL) {}
Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
template <class T>
void freeData(typename list <T>::Node*& pHead)
{
}
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
freedata() is a free-standing function. Unlike class methods, free-standing functions have to be declared before they can be used. But, you can't forward-declare freedata() in this case since its argument depends on a type that needs to know what freedata() is. Catch-22.
To fix that, you could break up the declarations and implementations of the list and Node class, eg:
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list();
~list();
void clear();
private:
struct Node
{
Node();
Node(const T& t);
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
Node* pHead;
Node* pTail;
int numElements;
};
template <class T>
void freeData(typename list <T>::Node*& pHead)
{
...
}
template <class T>
list<T>::list() : numElements(0), pHead(NULL), pTail(NULL) { }
template <class T>
list<T>::~list() { freeData(pHead); }
template <class T>
void list<T>::clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
template <class T>
list<T>::Node::Node() : pNext(NULL), pPrev(NULL) {}
template <class T>
list<T>::Node::Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
But really, there is no reason for freedata() to be a free-standing function in this example. It should be a member of the list class instead, eg:
#include <iostream>
namespace custom
{
template <class T>
class list
{
public:
list() : numElements(0), pHead(NULL), pTail(NULL) { }
~list() { clear(); }
void clear() { freeData(pHead); numElements = 0; pHead = NULL; pTail = NULL; }
private:
struct Node
{
Node() : pNext(NULL), pPrev(NULL) {}
Node(const T& t) : data(t), pNext(NULL), pPrev(NULL) {}
T data; // data of type T
Node* pNext; // pointer to next node
Node* pPrev; // pointer to previous node
};
Node* pHead;
Node* pTail;
int numElements;
static void freeData(Node*& pHead)
{
...
}
};
} // end of namespace
int main()
{
custom::list <int> l1;
l1.clear();
return 0;
}
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Derived template-class access to base-class member-data
(3 answers)
Closed 3 years ago.
I'm coding a simple LinkedList class that is a child class to an abstract List class. After finishing the List class I started to code the LinkedList class, and I noticed that the compiler would not let me access the protected variables from the members of the List class directly, even though LinkedList is a child class of List. When I do not add the "this->" pointer before one of List's variables, I get an error that says the variable is not declared in the scope. I'm sure there is a simple explanation for this, but I can't figure out why the two protected variables in my List class and its members are not accessible from the members of the LinkedList class.
List:
template<typename T>
class List {
protected:
unsigned int numElements;
Node<T>* head;
public:
List();
~List();
virtual void append(T x) = 0;
virtual T remove() = 0;
virtual bool isEmpty();
};
template<typename T>
List<T>::List() {
numElements = 0;
head = NULL;
}
template<typename T>
List<T>::~List() {
while(NULL != head) {
Node<T>* newHead = head->getNext();
delete head;
head = newHead;
}
}
template<typename T>
bool List<T>::isEmpty() {
if (numElements)
return false;
return true;
}
LinkedList with one member example:
template<typename T>
class LinkedList: public List<T> {
public:
void append(T x);
T remove();
void append_tail(T x);
void insert(T x, int pos);
T remove_at(int pos);
void print();
int getNumElements();
};
template<typename T>
void LinkedList<T>::append(T x) {
// create a new node with its next as the head
Node<T>* appendNode = new Node<T>(x, this->head);
// set the head to this new node
this->head = appendNode;
this->numElements++;
}
Node class that is included (not very relevant)
#ifndef NODE_H
#define NODE_H
template<typename T>
class Node {
private:
T value;
Node * next;
public:
Node(T v, Node * n);
T getValue() const;
Node * getNext() const;
void setNext(Node * p);
};
template<typename T>
Node<T>::Node(T v, Node * n) {
value = v;
next = n;
}
template<typename T>
T Node<T>::getValue() const {
return value;
}
template<typename T>
Node<T>* Node<T>::getNext() const {
return next;
}
template<typename T>
void Node<T>::setNext(Node * n) {
this->next = n;
}
#endif
I have a header file for a program that utilizes singly linked list. The data that is originally stored in the nodes were integers, however, in an attempt to use the template class, I tried to convert the Node class and AnyList class to template classes; however, when I compile, an error message that says "'Node": use of class template requires template argument list" appears. I've seen examples of template classes, but there's a bit of confusion since I'm trying to make two template classes in one header file.
#ifndef ANYLIST_H
#define ANYLIST_H
#include<iostream>
#include <string>
using namespace std;
template <typename T>
class Node
{
public:
Node() : data(0), next(NULL) {}
Node(T& theData, Node *newNext) : data(theData), next(newNext){}
Node* getNext() const { return next; }
T getData( ) const { return data; }
void setData(T& theData) { data = theData; }
void setNext(Node *newNext) { next = newNext; }
~Node(){}
private:
T data;
Node *next; //pointer that points to next node
};
template <typename T>
class AnyList
{
friend ostream& operator<<(ostream& out, const AnyList<T>& theList);
public:
AnyList();
void insert(const T& elem);
int getNumOfElem() const;
void destroyList();
~AnyList();
private:
Node *first;
int count;
};
#endif
Simply put, Node<> and List<> are different templates. So you need to forward the template parameter from List to Node.
Replace
Node *first;
By
Node<T> *first;
This question already has answers here:
Understanding templates in c++
(2 answers)
Closed 7 years ago.
I'm implementing a singly linked list. Here's the node class
template <typename T> class node{
friend class slist<T>;
public:
explicit node():data(0), next(NULL){}
private:
T data;
node<T> *next;
};
And here's the list class.
template<typename T> class slist{
public:
slist():head(NULL){}
bool empty(){
return head == NULL;
}
void add_front(const T& data){
if(head == NULL){
node<T>* n = new node<T>();
n->data = data;
n->next = NULL;
head = n;
return;
}
node<T>* n = new node<T>();
n->data = data;
n->next = head;
head = n;
}
void remove_front(){
if(head == NULL) return;
node<T>* old = head;
head = old->next;
delete old;
}
void print_list(){
if(head == NULL) return;
while(!empty()){
std::cout<<head->data<<std::endl;
head = head->next;
}
}
~slist(){
while(!empty()) remove_front();
}
private:
node<T>* head;
};
The implementation works perfectly fine if I declare the members in the node as public. However the moment I declare them private and make the slist a friend class, I get the following error.
In file included from src.cpp:3:
./slist.hpp:5:28: error: redefinition of 'slist' as different kind of symbol
template<typename T> class slist{
^
./node.hpp:4:15: note: previous definition is here
friend class slist;
I can obviously find other implementation of single linked list, but I'm trying to understand what's going wrong here. So please refrain from unsolicited advice as "google it". Thanks.
You need to forward declare the List class as a template class:
#include <iostream>
template<typename T> class List; //<< fwd decl
template<typename T> class Node {
int i;
public:
friend class List<T>; //<< usage same as you have now
Node() : i(123) {}
int value() { return i; }
};
template<typename T> class List { //<< definition
public:
List(Node<T>* node) { node->i++; }
};
int main() {
Node<int> node{};
List<int> list{&node};
std::cout << node.value() << "\n";
}
http://ideone.com/2RUWgj
The friend class declaration needs it's own template parameter declaration without shadowing the enclosing classes template parameters:
template<typename U> class slist; // Forward declare slist
template <typename T>
class node{
template<typename U> // <<<<<
friend class slist<U>;
// ^ <<<<<
// ...
};