const and pointers (a node example) - c++

Could you please tell me why I get this error:
source_file.cpp(41) : error C2664: 'void std::vector<Node<int> *,std::allocator<_Ty>>::push_back(Node<int> *const &)'
: cannot convert argument 1 from 'const Node<int> *' to 'Node<int> *&&'
when I call the AddChild method?
Here's my class definition/implementation:
template<class T>
class Node
{
private:
T _value;
vector<Node*> children;
public:
Node(T value);
Node(const Node<T>& node);
void AddChild(const Node<T>* node);
T getValue() const;
vector<Node<T>*> returnChildren() const;
~Node();
};
template <class T>
Node<T>::Node(T value):_value(value)
{
}
template <class T>
Node<T>::Node(const Node& node):_value(node.getValue()),
children(node.returnChildren())
{
}
template <class T>
void Node<T>::AddChild(const Node* node)
{
children.push_back(node);
}
template <class T>
T Node<T>::getValue() const
{
return _value;
}
template <class T>
vector<Node<T>*> Node<T>::returnChildren() const
{
return children;
}
template <class T>
Node<T>::~Node()
{
for (vector<Node*>::iterator it=children.begin() ; it!=children.end() ; it++)
{
delete (*it);
}
}

children contains pointers-to-non-const.
The node parameter is a pointer-to-const.
Those types are incompatible.
Either store pointers-to-const in children, or make the node parameter a pointer-to-non-const.

Related

No intellisense for std::shared_ptr in template class header file in VS2017

I'm new to std::shared_ptr and trying to use it in linked list implementation. The code is:
#pragma once
#include <memory>
template <typename T>
class Node
{
public:
Node();
Node(const T& anItem);
Node(const Node& anNode);
T getItem() const;
std::shared_ptr<Node<T>> getNext() const;
std::shared_ptr<Node<T>> getPrev() const;
void setItem(const T& anItem);
void setNext(std::shared_ptr<Node<T>> nextNodePtr);
void setPrev(std::shared_ptr<Node<T>> prevNodePtr);
private:
T item;
std::shared_ptr<Node<T>> next;
std::shared_ptr<Node<T>> prev;
};
template <typename T>
Node<T>::Node(): next(nullptr), prev(nullptr) {}
template <typename T>
Node<T>::Node(const T& anItem) : next(nullptr), prev(nullptr), item(anItem) {}
template <typename T>
Node<T>::Node(const Node& anNode) : next(anNode.getNext()), prev(anNode.getPrev()), item(anNode.getItem()) {}
template <typename T>
T Node<T>::getItem() const
{
return item;
}
template <typename T>
std::shared_ptr<Node<T>> Node<T>::getNext() const
{
return next;
}
template <typename T>
std::shared_ptr<Node<T>> Node<T>::getPrev() const
{
return prev;
}
template <typename T>
void Node<T>::setItem(const T& anItem)
{
item = anItem;
}
template <typename T>
void Node<T>::setNext(std::shared_ptr<Node<T>> nextNodePtr)
{
next = nextNodePtr;
}
template <typename T>
void Node<T>::setPrev(std::shared_ptr<Node<T>> prevNodePtr)
{
prev = prevNodePtr;
}
This is in a header file. In any of these member functions, dereferencing the shared pointer doesn't show up the members and methods.
For example, suppose that in setPrev() I typed the following:
prev->
Now if it's a raw pointer (I tested with raw pointer), intellisense will show the members and methods available. But for std::shared_ptr intellisense doesn't work, and the only thing I saw is the methods of std::shared_ptr itself (operator* for example). I'm wondering what I did wrong?
Additionally, if I type (*prev). VS2017 simply tells me:
IntelliSense: 'No members available'
BTW it works in main.cpp, just not working in the header file, which is painful as I have to check the header files frequently, so I'm wondering I did something wrong with the smart pointer.

syntax error in inheritance

I've been having some trouble with these nodes I'm trying to inherit. I've looked at a lot of examples online but can't figure out what I'm dong wrong.
My compiler is giving me these messages:
error: expected identifier before 'public'
error: expected '{' before 'public'
error: expected unqualified-id before 'public'
Any help would be much appreciated :)
template <typename T>
class Node
{
protected:
Node<T>* next;
Node<T>* prev;
T* data;
public:
Node();
~Node();
Node* getNext();
Node* getPrev();
void setNext(Node<T>*);
void setPrev(Node<T>*);
T* getData();
void setData(T*);
};
template <typename T>
class HeadNode : public Node<T>
{
public:
HeadNode();
~HeadNode();
};
template <typename T>
class TailNode : public Node<T>
{
public:
TailNode(Node<T>*);
~TailNode();
};
template <typename T>
class InternalNode : public Node<T>
{
public:
InternalNode(Node<T>*, Node<T>*, T*);
~InternalNode();
};
template <typename T>
Node<T>::Node()
{
next = 0;
prev = 0;
data = 0;
}
template <typename T>
Node<T>::~Node()
{
//delete data;
}
template <typename T>
Node<T>* Node<T>::getNext()
{
return next;
}
template <typename T>
Node<T>* Node<T>::getPrev()
{
return prev;
}
template <typename T>
void Node<T>::setNext(Node<T>* n)
{
next = n;
}
template <typename T>
void Node<T>::setPrev(Node<T>* n)
{
prev = n;
}
template <typename T>
T* Node<T>::getData()
{
return data;
}
template <typename T>
void Node<T>::setData(T* nData)
{
delete data;
data = nData;
}
template <typename T>
HeadNode<T>::HeadNode() : public Node<T>()
{
next = new TailNode<T>(this);
}
template <typename T>
HeadNode<T>::~HeadNode()
{
}
template <typename T>
TailNode<T>::TailNode(Node<T>* p) : public Node<T>()
{
prev = p;
}
template <typename T>
TailNode<T>::~TailNode()
{
}
template <typename T>
InternalNode<T>::InternalNode(Node<T>* n, Node<T>* p, T* nData): public Node<T>()
{
next = n;
prev = p;
data = nData;
}
template <typename T>
InternalNode<T>::~InternalNode()
{
//delete data;
}
I'm not so good at C++, but this passed the compiler.
remove public from the initialization at constructors
add Node<T>:: to where child classes want to use member of parent class
add virtual to the destructor of Node so that destructors of child classes will be called on deleting
template <typename T>
class Node
{
protected:
Node<T>* next;
Node<T>* prev;
T* data;
public:
Node();
virtual ~Node(); // add virtual
Node* getNext();
Node* getPrev();
void setNext(Node<T>*);
void setPrev(Node<T>*);
T* getData();
void setData(T*);
};
template <typename T>
class HeadNode : public Node<T>
{
public:
HeadNode();
~HeadNode();
};
template <typename T>
class TailNode : public Node<T>
{
public:
TailNode(Node<T>*);
~TailNode();
};
template <typename T>
class InternalNode : public Node<T>
{
public:
InternalNode(Node<T>*, Node<T>*, T*);
~InternalNode();
};
template <typename T>
Node<T>::Node()
{
next = 0;
prev = 0;
data = 0;
}
template <typename T>
Node<T>::~Node()
{
//delete data;
}
template <typename T>
Node<T>* Node<T>::getNext()
{
return next;
}
template <typename T>
Node<T>* Node<T>::getPrev()
{
return prev;
}
template <typename T>
void Node<T>::setNext(Node<T>* n)
{
next = n;
}
template <typename T>
void Node<T>::setPrev(Node<T>* n)
{
prev = n;
}
template <typename T>
T* Node<T>::getData()
{
return data;
}
template <typename T>
void Node<T>::setData(T* nData)
{
delete data;
data = nData;
}
template <typename T>
HeadNode<T>::HeadNode() : Node<T>() // remove public
{
Node<T>::next = new TailNode<T>(this); // add Node<T>::
}
template <typename T>
HeadNode<T>::~HeadNode()
{
}
template <typename T>
TailNode<T>::TailNode(Node<T>* p) : Node<T>() // remove public
{
Node<T>::prev = p; // add Node<T>::
}
template <typename T>
TailNode<T>::~TailNode()
{
}
template <typename T>
InternalNode<T>::InternalNode(Node<T>* n, Node<T>* p, T* nData): Node<T>() // remove public
{
Node<T>::next = n; // add Node<T>::
Node<T>::prev = p; // add Node<T>::
Node<T>::data = nData; // add Node<T>::
}
template <typename T>
InternalNode<T>::~InternalNode()
{
//delete data;
}

Nested template class constructor

I the compiler can't find the definition of my constructor for the nested class.
My nested class Node is in the middle and the constructor is at the end.
Errors:
error C2244: 'CircularDoubleDirectedList::Node::Node' : unable
to match function definition to an existing declaration see
declaration of 'CircularDoubleDirectedList::Node::Node'
definition
'CircularDoubleDirectedList::Node::Node(const T &)'
existing declarations
'CircularDoubleDirectedList::Node::Node(const T &)'
Code:
#ifndef CIRCULARDOUBLEDIRECTEDLIST_H
#define CIRCULARDOUBLEDIRECTEDLIST_H
#include "ICircularDoubleDirectedList.h"
template <typename T> class CircularDoubleDirectedList;
template <typename T> class Node;
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
public:
//Variabels
Node<T>* current;
int nrOfElements;
direction currentDirection;
//Functions
CircularDoubleDirectedList();
~CircularDoubleDirectedList();
void addAtCurrent(const T& element) override;
private:
template <typename T>
class Node
{
public:
T data;
Node<T>* forward;
Node<T>* backward;
Node(const T& element);// The constructor
};
};
template <typename T>
CircularDoubleDirectedList<T>::CircularDoubleDirectedList(){
this->nrOfElements = 0;
this->current = nullptr;
this->currentDirection = FORWARD;
}
template <typename T>
CircularDoubleDirectedList<T>::~CircularDoubleDirectedList(){
//TODO: Destroy all nodes
}
template <typename T>
void CircularDoubleDirectedList<T>::addAtCurrent(const T& element){
Node<T>* newNode = new Node<T>(element);
newNode->data = element;
if (this->nrOfElements == 0){
newNode->forward = newNode;
newNode->backward = newNode;
}
else{
//this->current->forward = newNode;
//this->current->forward->backward = newNode;
}
//this->current = newNode;
}
template <typename T>
CircularDoubleDirectedList<T>::Node<T>::Node(const T& element){
this->data = element;
}
#endif
First, the forward-declared template <typename T> class Node; is not the same as CircularDoubleDirectedList::Node - the former is a global class template, the latter is a nested class.
Second, you don't need to declare CircularDoubleDirectedList::Node as a template (and if you do, you have to use another template parameter name for it, not T). But as I understand, for this case you should just make it non-template, so:
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
private:
class Node
{
public:
T data;
Node* forward;
Node* backward;
Node(const T& element);// The constructor
};
public:
Node* current;
//...
};
template <typename T>
CircularDoubleDirectedList<T>::Node::Node(const T& element){
this->data = element;
}
You have two class templates named Node, while in reality you want one non-template class named Node. You have forward-declared ::Node<T>, and you have the nested ::CircularDoubleDirectedList<T>::Node<U>.
If you really want it like that, you'll have to add another template keyword to the constructor definition:
template <typename T> //because CircularDoubleDirectedList is a template
template <typename U> //because Node is a template
CircularDoubleDirectedList<T>::Node<U>::Node(const T& element) : data(element)
{}
However, I can't see a single reason to have Node be a template. Inside CircularDoubleDirectedList<T>, do you want to use nodes with type other than T? If not, make Node a normal non-template class:
template <typename T>
class CircularDoubleDirectedList :
public ICircularDoubleDirectedList<T>{
public:
//Variabels
Node<T>* current;
int nrOfElements;
direction currentDirection;
//Functions
CircularDoubleDirectedList();
~CircularDoubleDirectedList();
void addAtCurrent(const T& element) override;
private:
class Node
{
public:
T data;
Node* forward;
Node* backward;
Node(const T& element);// The constructor
};
};
template <typename T>
CircularDoubleDirectedList<T>::Node::Node(const T& element) : data(element)
{}

Template Class data type

I've created this pretty simple dynamic list which is implemented with a template class:
Node.h
template <class T> class Node
{
public:
typedef T data_type;
typedef T& reference_type;
void setData(data_type);
void setNextNull();
void setNext(Node*);
reference_type getData();
Node* getNext();
private:
data_type data;
Node* next;
};
template <class T> void Node<T>::setData(data_type _data)
{
data=_data;
}
template <class T> void Node<T>::setNextNull()
{
next=NULL;
}
template <class T> void Node<T>::setNext(Node* _next)
{
next=_next;
}
template <class T> typename Node<T>::reference_type Node<T>::getData()
{
return data;
}
template <class T> typename Node<T>::Node* Node<T>::getNext()
{
return next;
}
List.h
#ifndef LIST_H
#define LIST_H
#include <Node.h>
template <class T> class List
{
public:
typedef Node<T> node_type;
typedef node_type* node_pointer;
typedef T data_type;
typedef T& reference_type;
List();
void push_back(data_type);
reference_type at(int);
void clear();
void swap(int,int);
int size();
private:
int list_size = 0;
node_pointer head, tail;
};
template <class T> List<T>::List()
{
head=NULL;
}
template <class T> void List<T>::push_back(data_type data)
{
if(head == NULL) {
head = new node_type;
head->setData(data);
tail = head;
} else {
node_pointer temp = new node_type;
temp->setData(data);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
list_size++;
}
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
node_pointer pointer=head;
for(int i=0; i<x; i++)
pointer=pointer->getNext();
return pointer->getData();
}
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
for(int i=0; i<list_size; i++) {
node_pointer temp = pointer;
pointer=pointer->getNext();
delete(temp);
}
head=NULL;
list_size=0;
}
template <class T> void List<T>::swap(int x, int y)
{
data_type buffer=at(x);
at(x)=at(y);
at(y)=buffer;
}
template <class T> int List<T>::size()
{
return list_size;
}
#endif // LIST_H
The list works perfectly with any form of data type, except when i use a class with a parameter inside it's constructor, then I get this error:
include/Node.h error: no matching function for call to ‘Player::Player()’
What am I doing wrong??
UPDATE 1
I've added a simple constructor as suggested but I get the same error
template <class T> Node<T>::Node(data_type _data)
{
data=_data;
}
You probably haven't defined a default constructor for your Player class. Just insert an empty constructor
Player() {}
And your problem will likely to be solved.
When you write a template method and use it in the main function like this:
Node<Player>
The compiler automatically calls the constructor of the Player class.
If you didn't define any constructors in Player, the compiler will use default constructor. However, any constructor you defined will hide the default one and force you to use this one.
For instance, a constructor like
Player(string, int, int)
Prevents you to create an object like this:
Player *p = new Player();
However, if you haven't written the constructor, the piece of code above would've worked just fine.
That's why your template needs a default constructor, iff you defined a parameterized constructor.
Your class Node should have a constructor which take a T so you can construct your T by copy instead of requiring to have a default constructor and copy.
your Node class would be something like:
template <class T>
class Node
{
public:
Node(const T& data) : data(data), next(0) {}
void setNextNull();
void setNext(Node*);
const T& getData() const { return data; }
T& getData() { return data; }
Node* getNext();
private:
T data;
Node* next;
};
and so you transform
head = new node_type;
head->setData(data);
by
head = new node_type(data);

non member function template of a template class

template <class T>
class BTree
{
private:
T Data;
BTree* Right;
BTree* Left;
public:
BTree();
BTree(T);
~BTree();
void SetData(T);
T GetData();
void SetRight(BTree*);
BTree* GetRight();
void SetLeft(BTree*);
BTree* GetLeft();
};
Is this the way to declare a non member function template?I seriously have some doubts about these definitions.
template <class T>
BTree<T>* NewNode();
template <class T>
BTree<T>* NewNode(T);
this below does not work!! gives me an error
template <class T>
BTree<T>* NewNode()
{
BTree<T>* Node=new BTree<T>;
return Node;
}
template <class T=int>
//template <class BTree>
BTree<T>* NewNode(T Num)
{
BTree<T>* Node=new BTree<T>(Num);
return Node;
}
int main()
{
BTree<int>* Root=NULL;
Root=NewNode(1); //it says undefined reference.
Root->SetLeft(NewNode(2));
Root->SetRight(NewNode(3));
return 0;
}
The error is as the following:
1.undefined reference to `BTree<int>* NewNode<int>(int)'
2.undefined reference to `BTree<int>::SetLeft(BTree<int>*)'
3.undefined reference to `BTree<int>::SetRight(BTree<int>*)'