I have this class called "Node". I've been considering renaming it "Tree", but either name makes about as much sense. This class implements a generic tree container. Each node can have any number of children. The basic header definition of the class is as follows:
template<class Elem>
class Node
{
public:
Node();
~Node();
Node(const Elem& value);
Node(const Node& rNode);
const Elem& operator*() const;
Elem& operator*();
Elem* operator->();
void operator=(const Elem& rhs);
Node* addChild(const Elem& value);
Node* addChild(Node childNode);
Node* addChild(Node* pChildNode);
HRESULT removeNode(DFSIterator<Node>& iter);
template <class Node, class List, class Iter> friend class DFSIterator;
private:
bool hasChild() const;
Node* m_pParentNode;
Elem m_value;
std::vector<Node*> m_childList;
static std::set<Node*> sNodeSet;
};
The header definition of my DFSIterator is:
template<class Item,
class List = std::vector<Item*>,
class Iter = typename std::vector<Item*>::iterator>
class DFSIterator
{
public:
DFSIterator(Item& rRootNode);
~DFSIterator();
DFSIterator* begin();
DFSIterator* operator++();
Item& operator*() const;
Item* operator->() const;
bool operator!=(const DFSIterator& rhs) const;
bool isDone() const;
operator bool() const {return !isDone();}
private:
template <class Node> friend class Node;
void initChildListIterator(Item* currentNode);
bool m_bIsDone;
Item* m_pRootNode;
Item* m_pCurrentNode;
ChildListIterator<Item>* m_pCurrentListIter;
std::map<Item*, ChildListIterator<Item, List, Iter>*> m_listMap;
};
Item is the iterator's alias for Node<Elem>.
The problem I am having is that I want to define iterators for this tree that the user can declare in a similar way to STL containers. I was thinking that putting typedef statements like typedef DFSIterator<Node<Elem>> dfs_iterator; would work fine. But whenever I add those statements into the header, I get the following error error C2512<Item>: no appropriate default constructor available. Wherever I try to go and use it.
So right now, to declare an iterator I have to do something like DFSIterator<Node<DataMap>> dfsIter = rRootNode.begin(); or DFSIterator<Node<DataMap>> dfsIter(rNode); if I don't want to start at the root node of the tree. What I want to be able to do is something more like Node<DataMap>::dfs_iterator it = rRootNode.begin(). Is there a way to do this that I am missing?
Note: I do want to change a few other things about this implementation. I don't really want the user to be passing a node element to the addChild() method. I'd rather have the user pass an iterator that is pointing to a node.
If you define dfs_iterator inside Node, then you can use it basically like you describe:
template<class Elem>
class Node
{
public:
typedef Node<Elem> Item;
template<
class List = std::vector<Item*>,
class Iter = typename std::vector<Item*>::iterator
> class dfs_iterator;
.
.
.
};
template<class Elem>
template<class List, class Iter>
class Node<Elem>::dfs_iterator
{
public:
.
.
.
};
and use
Node<DataMap>::dfs_iterator<> it = rRootNode.begin();
The only difference is that since dfs_iterator is a template, you have to specify the template parameters, even though they both can be defaulted.
Related
I have my doubly linked list class and I can implement its
Iterator& before(const Iterator& p)
and
Iterator& after(const Iterator& p)
methods but other classes(iterator, node) are implemented. How should I code these methods, any help will be appreciated
class Node {
public:
Node* next;
Node* prev;
Elem elem;
friend class Linkedlist;
Node(): next(NULL), prev(NULL)
{}
Node(Elem elem) : elem(elem)
{}
};
class Linkedlist {
private:
Node *head;
Node *tail;
int N;
public:
Iterator& before(const Iterator& p);
Iterator& after(const Iterator& p);
class Iterator {
private:
Node *iter;
//Iterator(Node* curr);
public:
friend class Linkedlist;
//rest of the methods
We need to take care of certain cases in mind before implementing before and after method. Like what if someone passed iterator of head as argument to before method.
Then we may have to return a local iterator with null pointer but returning a local with l-value reference is really a problem and same problem for after method if we pass iterator of tail as argument.
So instead of having before and after please try to have begin and end method with increment/decrement operator overload for traversing.
See interface of std::vector , std::list etc.
In summary, my problem is that I want to find a way to get an access to the element to which iterator is pointing from a derived class. The details are at the below.
I am implementing a sequence with a doubly linked list, referring to the book "Data Structures & Algorithms in C++" (written by Goodrich, Tamassia, Mount), page 255. The book defines class NodeSequence as a derived class of doubly linked list.
Here is the code. Firstly, I made a doubly linked list class with struct Node and class Iterator inside. (This is saved as "DList.h")
typedef int E;
class DList {
private:
struct Node {
E element;
Node* prev;
Node* next;
};
public:
class Iterator {
public:
E& operator*();//reference to the element
bool operator==(const Iterator& p) const;
bool operator!=(const Iterator& p) const;
Iterator& operator++();
Iterator& operator--();
friend class DList; //gives access to the DList
private:
Node* v; //pointer to the node
Iterator(Node* u); //create from Node
};
public:
DList();
int size() const;
bool empty() const;
Iterator begin() const;
Iterator end() const;
void insertFront(const E& e);
void insertBack(const E& e);
void insert(const Iterator& p, const E& e);
void eraseFront();
void eraseBack();
void erase(const Iterator& p);
void printList();
private:
int n;
Node* header;
Node* trailer;
};
Next, I made a derived class of DList named "NodeSequence", which is defined as the following
#include "DList.h"
class NodeSequence : public DList{ //NodeSequence class inherits DList class
public:
Iterator atIndex(int i) const ; //get position from index
int indexOf(const Iterator& p) const; //get index from position
};
Finally, I wanted to test my code, so I demonstrated as the following.
int main() {
NodeSequence test;
test.insertBack(5);
test.insertBack(4);
test.insertBack(3);
test.insertBack(2);
test.insertBack(1);
NodeSequence::Iterator p= test.atIndex(1);
cout << (p.v)->element() << endl;
// I expected 4, but it gives compile error, it says I can't access to p.v because it is a private member
}
Is there any way I can get an access to the private element (which is a pointer) of the iterator? I do not want to change Node* v from private to public.
i am writing this code a generic list , now in this generic list i did a class for iterator that helds two parameters : one is a pointer to the list he points to .
and the other one points to the element in the list he points to ..
now i need to write an insert function that inserts a new element to a given list , with the following rules :: where i insert a new node to the list, and in this function if the iterator poiints to the end of the list the we add the new node to the end of the list else we insert the node one place before the node that the iterator currently points to , and if the iteratot points to a different node then thats an error .
now i want the iterator to be defoult so in case in the tests someone called the function with one parameter i want the iterator to be equal to the end element of the list.
the function end i wrote it inside of the list.
now in the insert function i did that but i get this error :
cannot call member function "List::iterator List::end()"without object
.
#include <iostream>
#include <assert.h>
#include "Exceptions.h"
template <class T>
class List {
public:
List();
List(const List&);
~List();
List<T>& operator=(const List& list);
template <class E>
class ListNode {
private:
ListNode(const E& t, ListNode<E> *next): data(new E(t)), next(next){}
~ListNode(){delete data;}
E* data;
ListNode<E> *next;
public:
friend class List<E>;
friend class Iterator;
E getData() const{
return *(this->data);
}
ListNode<E>* getNext() const{
return this->next;
}
};
class Iterator {
const List<T>* list;
int index;
ListNode<T>* current;
Iterator(const List<T>* list, int index): list(list),
index(index),current(NULL){
int cnt=index;
while (cnt > 0) {
current = current->next;
cnt--;
}
}
friend class List<T>;
friend class ListNode<T>;
public:
// more functions for iterator
};
Iterator begin() const ;
Iterator end() const;
void insert(const T& data, Iterator iterator=end());//here i get the error
void remove(Iterator iterator);
class Predicate{
private:
T target;
public:
Predicate(T i) : target(i) {}
bool operator()(const T& i) const {
return i == target;
}
};
Iterator find(const Predicate& predicate);
class Compare{
private:
T target;
public:
Compare(T i) : target(i) {}
bool operator()(const T& i) const {
return i < target;
}
};
bool empty() const;
int compareLinkedList(ListNode<T> *node1, ListNode<T> *node2);
private:
ListNode<T> *head;
ListNode<T> *tail;
int size;
};
any help would be amazing ! cause i don't know why such a mistake apears .
//insert function just in case :
template <typename T>
void List<T>::insert(const T& data, Iterator iterator=end()){
if(iterator.list!=this){
throw mtm::ListExceptions::ElementNotFound();
return;
}
ListNode<T> *newNode = new ListNode<T>(data, iterator.current);
if(iterator.index==size){
if (head == NULL) {
head = newNode;
tail=newNode;
}else{
Iterator temp(this,size-1);
temp.current->next=newNode;
}
//newNode->next=this->end().current;
}
else {
if (head == NULL) {
head = newNode;
tail=newNode;
}
else {
Iterator temp1(this,iterator.index-1);
temp1.current->next=newNode;
newNode->next=iterator.current->next;
}
}
size++;
}
void insert(const T& data, Iterator iterator=end());
This is the offending line. A default argument cannot be the result of a member function call. The right tool to achieve what you want is overloading.
void insert(const T& data, Iterator iterator);
void insert(const T& data) { insert(data, end()); }
Here we still defer to the insert function you implemented, but we call end from within the overloads body, where it's allowed.
Don't worry about the indirect call. This is a very small function that's defined inside the class declaration itself. Any decent compiler will inline it completely.
I am required to implement these two methods in this class. Elem& operator*() and Elem* operator->(). The only issue whoever is that the Iterator class is defined within a Map Class. While the Elem is defined in the private section of the parent class. The catch is that I am not allowed to modify the the .h file of the class.
class Iterator{
public:
Iterator(){}
explicit Iterator(Elem *cur):_cur(cur) {}
Elem& operator*();
Elem* operator->();
// Iterator operator++(int);
bool operator==(Iterator it);
bool operator!=(Iterator it);
private:
Elem* _cur;
};
Here is my attempted implemnetation of the function. However does not work as it says the struct is private.
Map::Elem& Map::Iterator::operator*(Iterator it){
//do stuff
}
The class is defined within another class. Which the struct is defined in under the private section. I am not really sure how I am supposed to be returning an Elem& or Elem* from within the Iterator class, if the Elem structure is private. However I suspect it has something to do with the Elem* _cur; defined within the private function of the Iterator class.
Here is the struct defined within the Map class. If that makes sense.. its private...
private:
struct Elem {
KEY_TYPE key;
VALUE_TYPE data;
Elem *left;
Elem *right;
};
Elem *_root; // a dummy root sentinel
int _size;
In case what I included does not work, here is the full class definition. Just wanted to include the examples above to include less code.
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <string>
using namespace std;
typedef string KEY_TYPE;
typedef string VALUE_TYPE;
class Map{
struct Elem; //declaration of an interal structure needed below...
public:
//---Constructors and destructors---
Map(); // constructs empty Map
Map(const Map &rhs); // copy constructor
~Map(); // destructor
// assignment operator
Map& operator=(const Map &rhs);
// insert an element; return true if successful
bool insert(KEY_TYPE, VALUE_TYPE);
// remove an element; return true if successful
bool erase(KEY_TYPE);
// return size of the Map
int size() const;
// return an iterator pointing to the end if an element is not found,
// otherwise, return an iterator to the element
class Iterator;
Iterator find(KEY_TYPE) const;
// Iterators for accessing beginning and end of collection
Iterator begin() const;
Iterator end() const;
// overloaded subscript operator
VALUE_TYPE& operator[](KEY_TYPE);
// output the undering BST
ostream& dump(ostream& out) const;
// a simple Iterator, won't traverse the collection
class Iterator{
public:
Iterator(){}
explicit Iterator(Elem *cur):_cur(cur) {}
Elem& operator*();
Elem* operator->();
// Iterator operator++(int);
bool operator==(Iterator it);
bool operator!=(Iterator it);
private:
Elem* _cur;
};
private:
struct Elem {
KEY_TYPE key;
VALUE_TYPE data;
Elem *left;
Elem *right;
};
Elem *_root; // a dummy root sentinel
int _size;
// helper method for inserting record into tree.
bool insert(Elem *& root, const KEY_TYPE& key, const VALUE_TYPE& data);
// helper method for print tree
void printTree(ostream& out, int level, Elem *p) const;
// common code for deallocation
void destructCode(Elem *& p);
// common code for copy tree
void copyCode(Elem* &newRoot, Elem* origRoot);
};
ostream& operator<< (ostream&, const Map&);
#endif
Any help would be awesome. Been making the rounds on google with no such luck.
The issues is not that Elm is private. Change
Map::Elem& Map::Iterator::operator*(Iterator it){
//do stuff
}
to
Map::Elem& Map::Iterator::operator*(){
//do stuff
}
because the former does not match the signature declared in the header. That causes the defined operator overload to not be in the scope of the class.
I have a class like this:
template <class T>
class bag
{
private:
typedef struct{T item; unsigned int count;} body;
typedef struct _node{_node* prev; body _body; _node* next;}* node;
struct iterator{
enum exception{NOTDEFINED, OUTOFLIST};
body operator*();
explicit iterator();
explicit iterator(const iterator&);
iterator& operator=(const iterator&);
iterator& operator++(int);
iterator& operator--(int);
bool operator==(const iterator&) const;
bool operator!() const;
private:
node current;
friend class bag;
};
node head;
node foot;
iterator _begin;
iterator _end;
/* ... */
public: /* ... */
bag();
const iterator& begin;
const iterator& end;
};
In the bag() I have to set the reference begin to _begin, and end to _end.
begin = _begin;
end = _end;
But I think this line
begin = _begin;
invokes bag::iterator::operator=() function.
How can i avoid that?
References can't be assigned, only initialised. So you will need to initialise them in the constructor's initialisation list:
bag() : begin(_begin), end(_end) {}
However, it's more conventional (and also reduces the class size) to get these using accessor functions rather than public references:
const iterator& begin() {return _begin;}
const iterator& end() {return _end;}
Use initializer list:
bag::bag() : begin(begin_), end(end_)
{
}
As Mike said, you have to initialise a reference where you declare it, you can't change it afterwards. The initialiser list is the most idiomatic solution if you don't have to modify the references once the object is constructed, but in the case you foresee you have to change them, there are still the good old pointers:
public: /* ... */
bag();
iterator *begin;
iterator *end;
A class containing reference members essentially becomes unassignable (because references can't be reseated).
It looks like your Bag is duplicating the same data in several members (extra burden to keep duplicated values in synch).
Instead you could do what the standard library does: create and return the iterator by value from begin() and end() methods.
template <class T>
class bag
{
struct node { /*...*/ }
/* ... */
node* head; //why would you want to typedef away that these are pointers?
node* tail;
public:
class iterator {
iterator(node*);
/* ... */
};
iterator begin() { return iterator(head); }
iterator end() { return iterator(tail); }
//also you might need const_iterators
};