I'm trying to implement by own generic/template ArrayList and I've run into a snag. I know the error comes from not having somewhere in the argument list but for me I can't figure it out here, I get a different error if I do. For brevity I've removed functions I'm unable to debug until this one is debugged first.
//ArrayList.h//
#include <iostream>
#include <string>
using namespace std;
template <class T>
class ArrayList {
private:
class Node {
private:
Node* next;
Node* prev;
T* element;
public:
Node();
Node( T* );
Node( Node* /*new prev*/, T* );
~Node();
void setNext( Node* );
Node* getNext();
};
int size;
int maxSize;
int current_index;
Node* myArrayList;
Node* curr;
Node* head;
Node* tail;
public:
};
Implementation of "Node* getNext();" in my cpp file.
//ArrayList.cpp//
#include "arraylist.h"
...
template <class T>
ArrayList::Node* ArrayList::Node::getNext() {
return this->next;
}
Trying to insert behind :: hasn't worked very well... Node* becomes undefined if I put before it.
template <class T>
ArrayList<T>::Node* ArrayList::Node::getNext() {
return this->next;
}
Then I get ";" expected before "*".
Try this:
template <class T>
typename ArrayList<T>::Node* ArrayList<T>::Node::getNext()
{
return this->next;
}
Or in C++11 (Demo):
template <class T>
auto ArrayList<T>::Node::getNext() -> Node*
{
return this->next;
}
or just use an in-line definition, which is recommended for simple accessors.
You need to define your member functions as such :
template <class T>
typename ArrayList<T>::Node* ArrayList<T>::Node::getNext() {
return this->next;
}
Related
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)
{}
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);
I want to create a factory, that returns AVLNode, if BinaryTree is AVLTree, and Node if the tree is not AVL. I have following code:
#include "BinaryTree.h"
#include "AVLTree.h"
class NodeFactory {
public :
template <class T>
static Node<T>* getNode(BinaryTree<T>* tree);
};
template <class T>
Node<T>* NodeFactory::getNode(BinaryTree<T>* tree) {
if (tree->isAVL()) {
return new AVLNode<T>();
} else {
return new Node<T>();
}
}
UPD: (this is BinaryTree.h)
template <class T> class Node;
template <class T> class BinaryTree {
public:
BinaryTree() {
_isAVL = false;
root = new Node<T>();
}
bool isAVL() {
return _isAVL;
}
private:
T elem;
Node<T>* root;
bool _isAVL;
};
template <class T> class Node {
public:
Node() {
left = NULL;
right = NULL;
}
T get() {
return elem;
}
void setRight(const T elem) {
right = new Node<T>();
right->set(elem);
}
void setLeft(const T elem) {
left = new Node<T>();
left->set(elem);
}
private:
T elem;
Node* left;
Node* right;
};
I removed almost all methods to make code more readable.
Now i have this error during compilation: "expected initializer before '<' token". Also Qt do not highlights in Node, but highlights in BinaryTree
It's a syntax error. You need
template <class T> // or <typename T>
Node<T>* NodeFactory::getNode(BinaryTree<T>* tree) {
I'm trying to create my own template for a List class as a learning excercise. I've been having some trouble with template syntax though and i'm now getting the following error message..
main.cpp|Line 8|instantiated from here
error: template argument required for 'struct List'
In function 'int main()':
...
As far as i can tell i'm not misusing anything but this is my first time working with templates and would really appreciate someone looking through and letting me know what i'm doing wrong.
List.hpp:
#if !defined _LIST_HPP_
#define _LIST_HPP_
#include "Node.hpp"
///since we're creating a template everything must be defined in the hpp
template <typename ListType>
class List
{
public:
List();
bool Empty();
void PushFront();
void PushBack();
void PopBack();
Node<ListType>& GetHead();
private:
int _size;
Node<ListType>* _head;
Node<ListType>* _tail;
};
///implement List class here
template <typename ListType>
List<ListType>::List() : _head(0), _tail(0), _size(0)
{
}
template <typename ListType>
bool List<ListType>::Empty()
{
return _size == 0;
}
template <typename ListType>
void List<ListType>::PushFront()
{
_head = new Node<ListType>( _head , 0 );
if (!Empty())
_head->_prev->_next = _head; //set previous nodes _next to new _head
++_size;
}
template <typename ListType>
void List<ListType>::PushBack()
{
_tail = new Node<ListType>( 0 , _tail);
if (!Empty())
_tail->_next->_prev = _tail; // set old tails _prev to new tail
++_size;
}
template <typename ListType>
void List<ListType>::PopBack()
{
}
template <typename ListType>
Node<ListType>& List<ListType>::GetHead()
{
return _head;
}
#endif //define
Node.hpp:
#if !defined _NODE_HPP_
#define _NODE_HPP_
template<typename NodeType>
class Node{
public:
Node( Node* prev = 0, Node* next = 0);
void SetData(NodeType newData);
void GetData();
private:
friend class List;
NodeType _data;
Node* _next;
Node* _prev;
};
///implement Node
template <typename NodeType>
Node<NodeType>::Node(Node* prev, Node* next) : _prev(prev), _next(next)
{}
template <typename NodeType>
void Node<NodeType>::SetData(NodeType newData)
{
_data = newData;
}
template <typename NodeType>
void Node<NodeType>::GetData()
{
return _data;
}
#endif //define
Main.hpp
#include <iostream>
#include "List.hpp"
int main()
{
List<int> testl;
//test
testl.PushFront();
testl.GetHead().SetData(7); //Error thrown here??
std::cout << test1.GetHead().GetData() << std::endl;
return 0;
}
List is a class template, so you need to declare it as such in your friend declaration
template<typename ListType>
friend class List;
If you only want List<NodeType> to be a friend, you need to tell it that template argument, so then the friend declaration becomes
friend class List<NodeType>;
For this to work, it needs to know that List exists as a class template, so you need to forward-declare it at the top of Node.hpp:
template<typename ListType>
class List;
I'm trying to create my own templated List class as a practice excercise. I should have probably started smaller but there you go.. i'm getting the error "expected unqualified-id before '<' token " at each line that reads:
typedef <typename ListType>
I'm a student and I've been reading up on templates for a couple of hours but still cant figure this one out, any help would be much appreciated!
My hpp file for List:
#if !defined _LIST_HPP_
#define _LIST_HPP_
#include "Node.hpp"
///since we're creating a template everything must be defined in the hpp
typedef <typename ListType>
class List
{
public:
List();
bool Empty();
void PushFront();
void PushBack();
void PopBack();
Node<ListType>& GetHead();
private:
int _size;
Node<ListType>* _head;
Node<ListType>* _tail;
};
///implement List class here
typedef <typename ListType>
List<ListType>::List() : _head(0), _tail(0), _size(0)
{
}
typedef <typename ListType>
bool <ListType>Empty()
{
return !_size; //returns true if size = 0
}
typedef <typename ListType>
void List<ListType>::PushFront()
{
_head = new Node<ListType>( _head , 0 );
if (!Empty())
_head->_prev->_next = _head; //set previous nodes _next to new _head
++_size;
}
typedef <typename ListType>
void List<ListType>::PushBack()
{
_tail = new Node<ListType>( 0 , _tail);
if (!Empty())
_tail->_next->_prev = _tail; // set old tails _prev to new tail
++_size;
}
typedef <typename ListType>
void List<ListType>::PopBack()
{
}
typedef <typename ListType>
Node<ListType>& List<ListType>::GetHead()
{
return _head;
}
#endif //define
And i'll also include the templated node class hpp incase it could be something there that's throwing things off?
#if !defined _NODE_HPP_
#define _NODE_HPP_
//#include "Sprite.hpp"
template<typename NodeType>
class Node{
public:
Node( Node* prev = 0, Node* next = 0);
void SetData(NodeType newData);
void GetData();
private:
friend class List;
NodeType _data;
Node* _next;
Node* _prev;
};
///implement Node
template <typename NodeType>
Node<NodeType>::Node(Node* prev, Node* next) : _prev(prev), _next(next)
{}
template <typename NodeType>
void Node<NodeType>::SetData(NodeType newData)
{
_data = newData;
}
template <typename NodeType>
void Node<NodeType>::GetData()
{
return _data;
}
#endif //define
It’s template, not typedef.
And while we’re at it, your preprocessor tokens are invalid identifiers since they start with an underscore, which isn’t allowed here. Use something like LIST_HPP instead.
Finally, let’s take a look at your Empty definition:
typedef <typename ListType>
bool <ListType>Empty()
{
return !_size; //returns true if size = 0
}
First of all, this is missing the class name in the method name. Secondly, I dislike the conversion from a number to bool. Why not use an explicit comparison? That also obviates the comment, which is useless in itself since it merely paraphrases the code.
This leaves us with:
template <typename ListType>
bool List<ListType>::Empty()
{
return _size != 0;
}