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;
}
Related
I've been trying to work out the cause of an error I'm getting in the compiler, stating in the template file "Node.template" that 'node<Obj> does not name a type'.
I am new to class templates and have looked around for answers but I'm still not able to fix this particular problem.
Here's code for the two files:
//Node.h
#ifndef NODE_CAMERON_H
#define NODE_CAMERON_H
#include <string>
using namespace std;
namespace oreilly_A2 {
template <typename Obj>
class node {
public:
typedef std::string value_type;
node(); //constructor for node
node(const value_type& val, Obj* newNext); //constructor with parameters
void set_data(const value_type& new_data); //set the word that this node contains
void set_link(Obj* new_link); //set the 'next' Obj
void set_previous(Obj* new_prev);
value_type data() const; //return this node's word
const Obj* link() const; //return next
const Obj* back() const;
Obj* link(); //return next
Obj* back();
private:
Obj* next; //the next Obj
Obj* previous;
value_type word; //the word this node contains
};
}
#include "Node.template"
#endif
Node.template file:
//Node.template
template <typename Obj>
node<Obj>::node(const node::value_type& val=value_type(), Obj* newNext=NULL) {
word = val;
next = newNext;
}
template <typename Obj>
node<Obj>::~node() {}
template <typename Obj>
void node<Obj>::set_data(const value_type& new_data){
word = new_data;
}
template <typename Obj>
void node<Obj>::set_link(Obj* new_link){
next = new_link;
}
template <typename Obj>
void node<Obj>::set_previous(Obj* new_prev) {
previous = new_back;
}
template <typename Obj>
value_type node<Obj>::data() const { //return the word
return word;
}
template <typename Obj>
const Obj* node<Obj>::link() const { //return next node (const function)
return next;
}
template <typename Obj>
const Obj* node<Obj>::back() const { //return previous node (const)
return previous;
}
template <typename Obj>
Obj* node<Obj>::link() {
return next; //return next node (non-const)
}
template <typename Obj>
Obj* node<Obj>::back() { //return previous node (const)
return previous;
}
You declared the class template inside a namespace…
…but forgot the namespace when you defined its member functions.
There are indeed no types named node<Obj>, only types named oreilly_A2::node<Obj> (∀ Obj).
You need namespace oreilly_A2 { } in Node.template.
Also, please stop writing using namespace std in header files.
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'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;
}
Bit of an odd one, I successfully implemented my own templated linked list as an educational exercise a while back. Now I know it works, I've been using it to create a list of nodes that hold "Sprite" objects, and at the time I understood it but I went and looked back at it today and I'm really confused.
If you'd be kind enough to look at my implementation and help me figure out.
How does the program KNOW that _data (in Node) should be assigned an object of NodeType?? (if you'll excuse the poor phrasing) I mean I have that function SetData but I never even use it. And when I PushBack on the list for example, I just create a new Node of ListType, but I never set that node's data. The node constructor doesn't say _data = new NodeType or anything.
And yet I can call GetData() on any node in my list and get a Sprite object back. I mean I know it works, but I've forgotten how! Could someone take a look and remind me? It'd be much appreciated!
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);
NodeType* GetData();
Node* GetPrev();
Node* GetNext();
private:
template<typename ListType>
friend class List;
NodeType _data;
Node* _prev;
Node* _next;
};
///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>
NodeType* Node<NodeType>::GetData()
{
return &_data;
}
template <typename NodeType>
Node<NodeType>* Node<NodeType>::GetPrev()
{
return _prev;
}
template <typename NodeType>
Node<NodeType>* Node<NodeType>::GetNext()
{
return _next;
}
#endif //define
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();
void ClearList();
Node<ListType>* GetHead();
Node<ListType>* GetTail();
int NumberOfNodes();
private:
Node<ListType>* _head;
Node<ListType>* _tail;
int _size;
};
///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()) //this is the start of a new list, need to set _tail as well
_tail = _head;
else
_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()) //this is the start of a new list, need to set _head as well
_head = _tail;
else
_tail->_next->_prev = _tail; // set old tails _prev to new tail
++_size;
}
template <typename ListType>
void List<ListType>::PopBack()
{
if(!Empty()){
if(_tail != _head)
{
_tail = _tail->_next;
delete _tail->_prev; //delete memory at old tail
_tail->_prev = 0; //reassign new tails _prev pointer to null
}
else // We are deleting the last node so treatment is a little different.
{
delete _tail;
_tail = 0; _head = 0;
}
--_size;
}
}
template <typename ListType>
void List<ListType>::ClearList()
{
while(!Empty())
PopBack();
}
template <typename ListType>
Node<ListType>* List<ListType>::GetHead()
{
return _head;
}
template <typename ListType>
Node<ListType>* List<ListType>::GetTail()
{
return _tail;
}
template <typename ListType>
int List<ListType>::NumberOfNodes()
{
return _size;
}
#endif //define
The constructor doesn't explicitly do anything about _data, so it default initializes it*. In other words, after construction, _data is a default constructed NodeType. It NodeType were not default constructible, the template specialization wouldn't compile. The program "knows" to do this initialization because hopefully your compiler follows the rules set out in the C++ standard.
As for knowing the type, the compiler essentially replaces NodeType for which ever type you instantiate the template with and creates a new type using this replacement. So Node<std::string> would result in a type where_datais of typestd::string`.
if NodeType were a promitive type, then there would be no initialzation, and _data would hold any old garbage value.
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;