I've just started with learning C++ and I need to write a generic linked list and iterator. This is the code that I wrote (list.h), but I think it is not correct. It does not work and I am not sure that it is generic.
#include <iostream>
#include <cassert>
using namespace std;
using namespace ListExceptions;
class List;
class Iterator;
template<class T>
class Node{
private:
T data;
Node* previous;
Node* next;
friend class List;
friend class Iterator;
public:
Node(T element){
data = element;
previous = NULL;
next = NULL;
}
};
class List{
private:
Node* first;
Node* last;
public:
List(){
first = NULL;
last = NULL;
}
void pushBack(T element);
void insert(Iterator iter, T element);
Iterator remove(Iterator i);
Iterator find(const Predicate& predicate);
void sort(const Compare& comparer);
int getSize() const;
Iterator begin();
Iterator end();
};
class Iterator{
private:
Node* position;
Node* last;
friend class List;
public:
Iterator();
void next();
T getElement()const;
bool equals(Iterator b) const;
bool notEquals(Iterator b) const;
};
If someone can help me?
First thing is that the List and Iterator are non-templated classes, and you probably want to create Lists of a given type. You might consider refactoring the code so that both the Node and the Iterator are internal classes to the List type (it will make things simpler):
template <typename T>
class List {
public:
typedef T value_type;
class Iterator;
struct Node { // Internal to List<T>, so there will be different
// List<T>::Node for each instantiationg type T
// But you don't need the extra <T> parameter for List
// or Iterator
value_type data;
Node* next;
Node* last;
friend class List; // Inside List<T>, List by itself refers to List<T>
friend class Iterator;
};
//...
};
The alternative is a little more complex in code:
template <typename T> class List;
template <typename T> class Iterator;
template <typename T> class Node {
T data;
Node * next;
Node * last;
friend class List<T>;
friend class Iterator<T>;
};
template <typename T>
class List {
Node<T>* first; // note <T> required
//...
};
Related
I have the following code:
#include <iostream>
using namespace std;
template <class T>
class Iterator;
template <class T>
class List;
template <class T>
class List {
public:
struct Node;
Node* first;
friend class Iterator<T>;
List() :
first(NULL) { }
Iterator<T> begin() {
cout << first->data << endl;
return Iterator<T>(*this, first); // <--- problematic call
}
void insert(const T& data) {
Node newNode(data, NULL);
first = &newNode;
}
};
template <class T>
struct List<T>::Node {
private:
T data;
Node* next;
friend class List<T>;
friend class Iterator<T>;
Node(const T& data, Node* next) :
data(data), next(next) { }
};
template <class T>
class Iterator {
private:
const List<T>* list;
typename List<T>::Node* node;
friend class List<T>;
public:
Iterator(const List<T>& list, typename List<T>::Node* node) {
cout << node->data << endl;
}
};
int main() {
List<int> list;
list.insert(1);
list.begin();
return 0;
}
First I set the node data to "1" (int). Ater that I just pass it to the Iterator constructor, but it changes the value of node->data.
I printed node->data before and after the call:
1
2293232
I guess that 2293232 is an address of something, but I can't find the reason this happens.
When you write
void insert(const T& data) {
Node newNode(data, NULL);
first = &newNode;
}
Then:
You create an object on the stack
Point some (more) persistent pointer to its address
Destruct it as it goes out of scope
So you're left with garbage stuff.
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)
{}
So I'm working with templates and I've run into a problem. After I converted my code into templates I am no longer able to access the private members of my classes. I get the error that 'current' is a private member of 'Iterator'. So first I have each class:
template <class T>
struct nodeType {
T info;
nodeType<T> *link;
};
template <class T>
class Iterator {
public:
Iterator();
Iterator(nodeType<T> *);
T operator*();
bool IsNull();
Iterator<T> operator++();
Iterator<T> operator++(int);
bool operator==(const Iterator<T> &) const;
bool operator!=(const Iterator<T> &) const;
Iterator<T> &operator=(T);
private:
nodeType<T> *current;
};
template <class T>
class LinkedList {
public:
LinkedList();
LinkedList(const LinkedList<T> &);
~LinkedList();
void InsertHead(T);
Iterator<T> InsertAfter(T, Iterator<T>);
Iterator<T> Search(T);
bool IsEmpty();
void Print();
void DestroyList();
Iterator<T> Start();
Iterator<T> End();
const LinkedList<T> &operator=(const LinkedList<T> &);
private:
nodeType<T> *head;
};
Before I used templates I used the following code, but not current is private and this no longer works.
template <class T>
Iterator<T> LinkedList<T>::InsertAfter(T input, Iterator<T> marker) {
Iterator<T> newNode = new nodeType<T>;
Iterator<T> findNode = marker;
newNode = input;
newNode.current->link = findNode.current->link;
findNode.current->link = newNode.current;
return findNode;
}
Then I tried to do the following and It get no errors but when I called the InsertAfter function to add a new item to the list it doesn't show up. I did a cout newNode = input; and it shows the value I want to insert, but the nodes don;t seem to connect up. Why can't I use the previous code I was doing before? Like newNode.current->link = findNode.current->link;
template <class T>
Iterator<T> Iterator<T>::operator++() {
current = current->link;
return *this;
}
template <class T>
Iterator<T> Iterator<T>::operator++(int) {
Iterator<T> temp;
temp = *this;
++(*this);
return temp;
}
template <class T>
Iterator<T> LinkedList<T>::InsertAfter(T input, Iterator<T> marker) {
Iterator<T> newNode = new nodeType<T>;
Iterator<T> findNode = marker;
newNode = input;
newNode++ = findNode++;
findNode++ = newNode;
return findNode;
}
You can't do newNode.current within a member function of LinkedList, because current is private to Iterator. That's what private means - it is only accessible from member functions of the class it belongs in.
Clearly your "old" code was different. Possibly you had Iterator friend LinkedList in the old code. If you post your old code it might clear things up.
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;
}
so thats what i got going.
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator;
template <class T>
class List<T>::Iterator{
public:
Iterator& operator++();
i'm trying to implement like so:
template<class T>
typename List<T>::Iterator& List<T>::Iterator::operator++()
but it keeps telling me "Member declaration not found"
EDIT:
thats the entire relevent code:
template <class T>
class Node {
T data;
Node<T>* next;
public:
Node () : next(0){};
Node (const T& info, Node<T>* next = 0) : data(info), next(next){};
friend class List<T>;
friend class Iterator;
friend class ConstIterator;
};
template<class T>
class List{
Node<T> head;
int size;
void listSwap(Node<T>* node1, Node<T>* node2);
public:
class Iterator;
class ConstIterator;
List ();
List(const List<T>& list);
List& operator=(const List<T>& list);
ConstIterator begin() const;
Iterator begin();
ConstIterator end() const;
Iterator end();
void insert(const T& t);
void insert(const T& t,const Iterator& it);
void remove(const Iterator& it);
// template<class Function>
// ConstIterator find(Function f);
template<class Function>
Iterator find(Function f);
template<class Function>
void sort(Function f);
int getSize();
bool operator==(const List<T>& list2) const;
bool operator!=(const List<T>& list2) const;
~List();
};
template <class T>
class List<T>::Iterator{
List<T>* list;
Node<T>* index;
public:
Iterator(List<T> list);
Iterator(List<T> list, Iterator& it);
Iterator& operator++();
Iterator operator++(int);
T operator*();
bool operator==(const Iterator& iterator2);
bool operator!=(const Iterator& iterator2);
~Iterator();
friend class List<T>;
};
thought I think it is ok :/
so frustrating sometimes....
Thank you guys for the help!
You don't need template<class T> class List<T>::Iterator in the Iterator class definition if iterator is a nested class. Just class Iterator.
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator
{
public:
Iterator& operator++();
....
};
....
};
Either that, or you are missing the closing }; of your List class:
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator;
};
^^ HERE!
I see some obvious bugs, as the class List is not closed before you define List<T>::Iterator, but I presume it is so because you cut off some portion of your code.
Unfortunately, I was unable to reproduce your case. The following code:
class List {
int size;
public:
class Iterator;
};
template <class T>
class List<T>::Iterator {
public:
Iterator& operator++();
};
template <class T>
typename List<T>::Iterator& List<T>::Iterator::operator++() {
return *this;
}
int main() {
}
And it compiles just fine under g++ (4.6.3) and clang++ (3.1), so the problem is somewhere else which you are not showing us.
You first code sample seems to be shreeded beyond recognition.
As for your second (longer) section of code, I don't see anthing wrong with it aside from one suspect area. Your friend declarations inside Node will refer to some non-template Iterator and ConstIterator classes from global namespace. Meanwhile, Iterator and ConstIterator from List are templates that do not belong to global namespace. Were those friend declarations in Node supposed to refer to Iterator and ConstIterator from List or not?