In my everlasting effort to implement a link list I created a class-template representing the container (CursorList) and I have a seperate class-template that is supposed to be my iterator (CursorIterator).
In my CursorList I use a struct Node to represent elements of the list. I want to share this struct with my CursorIterator-Class (the iterator is pointing towards a Node). However this doesn't work as I want it to, I can't really get both classes to know the structures of Node.
CursorList.h
#ifndef CURSORLIST_H
#define CURSORLIST_H
#include "CursorIterator.h"
template <class T> class CursorList {
public:
CursorList() {}
typedef T value_type;
typedef CursorIterator<T> iterator;
bool empty() const;
int size() const;
T& front() const;
void push_front(const T& item);
void pop_front();
iterator begin() const;
iterator end() const;
iterator insert(iterator itr, const T& value);
iterator erase(iterator start, iterator stop);
iterator erase(iterator itr);
struct Node {
Node(const T& n_data, Node* n_prev, Node* n_next): data(n_data), prev(n_prev), next(n_next) {}
T data;
Node* prev;
Node* next;
};
private:
Node* m_head;
};
#endif //CURSORLIST_H
CursorIterator.h
#ifndef CURSORITERATOR_H
#define CURSORITERATOR_H
template <class T> class CursorIterator {
private:
typedef CursorIterator<T> iterator;
Node* m_rep;
public:
CursorIterator() {}
CursorIterator(Node* n): m_rep(n) {}
T& operator *();
iterator& operator = (const iterator& rhs);
bool operator != (const iterator& rhs) const;
bool operator == (const iterator& rhs) const;
iterator& operator ++();
iterator operator ++(int);
};
#endif //CURSORITERATOR_H
Related
I'm trying to create my own implementation of a doubly-linked list for learning purpose. I wanted to use a template class to do this. I have a few constructors that have the definition like this:
template <typename TYPE>
class DList {
public:
DList(const size_t size, const TYPE& val = TYPE());
template <typename ITER>
DList(ITER&& begin, ITER&& end);
};
(I have more code that I have omitted).
The first constructor copies the value provided size times (so DList<int>(5, 2) would copy the number 2, 5 times)
The second constructor copies a range (between 2 Iterators) in to the list. (so DList<int>(other.begin(), other.end()) would copy one data structure in to the DList)
The question is that how do I set the preference of the two constructors? For example if I'm instantizing my class with this line:
DList<int> listTest2(6, 2);
The compiler gets confused and chooses the iterator based constructor over the size constructor and throws errors. I want to keep the template iterator constructor because I have other classes like that one (that implements other data structures) and the iterators is a class inside the class. (so DList has a class inside it called iterator, see below for more info on what I mean).
Is there anyway to set a preference over which constructor gets called. I want it to work like how I can call std::vector<int>(other.begin, other.end) and std::vector<int>(2, 3) and both work.
I have attached the header file for my template class below:
template <typename TYPE>
class DList {
public:
struct Node {
Node* prev;
TYPE data;
Node* next;
};
class iterator {
public:
iterator();
iterator(const Node* node);
iterator(const iterator& it);
iterator& operator++(); // preincrement
iterator& operator--();
iterator operator++(int); // postincrement
iterator operator--(int);
iterator& operator=(const iterator& it);
iterator& operator-(int scale);
iterator& operator+(int scale);
bool operator==(const iterator& it);
TYPE& operator*();
TYPE& operator->();
Node* getNode();
private:
Node* data;
};
DList();
DList(const DList& other);
DList(const size_t size, const TYPE& val = TYPE());
template <typename ITER>
DList(ITER&& begin, ITER&& end);
iterator begin() const;
iterator end() const;
void clear();
void push_back(const TYPE& val);
void push_front(const TYPE& val);
void pop_back();
void pop_front();
void insert(size_t idx, const TYPE& val);
void insert(const DList<TYPE>::iterator it, const TYPE& val);
void remove(const TYPE& val);
size_t size() const;
const TYPE& operator[](size_t idx) const;
TYPE& operator[](size_t idx);
private:
Node* mHead; /// #todo convert to iterators?
Node* mTail;
size_t mSize;
};
First of all: observe that with
DList<int> listTest2(6, 2);
you call the wrong constructor because you pass the wrong first argument: the size/val contructor wait for a std::size_t for the first parameter, so an unsigned value. But you send 6, that is a signed value.
The right way to call the size/val constructor is
DList<int> listTest2(6U, 2);
Second; you use && (rvalue) references; so you can use C++11; so you can use decltype.
Not a great solution but if you really want that DList<int> (6, 2) call the size/val constructor, you can use SFINAE and enable the template constructor only when ITER typename support the unary * operation (access to pointed value, supported by iterators but not by simple integers), so
template <typename I, typename = decltype(*I{})>
DList (I && begin, I && end)
The following is a full working (minimal) example
#include <iostream>
#include <vector>
template <typename T>
struct DList
{
DList (std::size_t const size, T const & val = T{})
{ std::cout << "constructor 1" << std::endl; }
template <typename I, typename = decltype(*I{})>
DList (I && begin, I && end)
{ std::cout << "constructor 2" << std::endl; }
};
int main()
{
std::vector<int> vi { 2, 3, 5, 7, 11, 13 };
DList<int>(6, 2); // print constructor 1
DList<int>(vi.cbegin(), vi.cend()); // print constructor 2
}
I'm trying to implement a template class which is almost the same as the STL implementation of list.
Now i'm working on the range overload of the std::insert() function. The prototype is :
template <class InputIterator> iterator insert (const_iterator position, InputIterator first, InputIterator last);
The problem is : i can't get the first and last iterators to do anything. Whenever i'm trying to dereference them (*first), i'm getting an "illegal indirection" error at compilation. The only operation i can perform is first++, and when i'm trying it with a std::vector<int>::iterator, first is obviously returning the next element.
Here is the most important part of my class :
template <class T>
class List {
public:
typedef T value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef std::size_t size_type;
/* Structures / Classes */
struct Node {
Node* previous;
Node* next;
Node() : previous(this), next(this) {};
Node(Node* previous) : previous(previous), next(this) {};
};
struct DataNode : public Node {
value_type data;
DataNode(const_reference data) : Node(), data(data) {};
virtual ~DataNode() {};
};
class ListIterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
{
friend class List;
private:
Node* node;
public:
ListIterator() : node(0) {};
ListIterator(Node* ptr) : node(ptr) {};
ListIterator(const ListIterator& other) : node(other.node) {};
virtual ~ListIterator() {};
ListIterator& operator++() { node = node->next; return *this; };
ListIterator operator++(int) {
ListIterator tmp(*this);
operator++();
return tmp;
};
ListIterator& operator--() { node = node->previous; return *this; };
ListIterator operator--(int) {
ListIterator tmp(*this);
operator--();
return tmp;
};
bool operator==(const ListIterator& other) { return node == other.node; };
bool operator!=(const ListIterator& other) { return node != other.node; };
ListIterator& operator=(const ListIterator& other) {
if (this != &other) this->node = other.node;
return *this;
}
value_type& operator*() { return reinterpret_cast<DataNode*>(node)->data; }
};
class ConstListIterator : public std::iterator<std::bidirectional_iterator_tag, const value_type> {
/* same with const ... */
};
/* More typedefs... */
typedef ListIterator iterator;
typedef ConstListIterator const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
protected:
/* Class members */
Node* root; // at the end
size_type elementCount;
public:
/* functions... */
iterator insert(const_iterator position, const value_type& val);
iterator insert(const_iterator position, size_type n, const value_type& val);
template<class InputIterator>
iterator insert(const_iterator position, InputIterator first, InputIterator last);
iterator insert(const_iterator position, value_type&& val);
iterator insert(const_iterator position, std::initializer_list<value_type> il);
/* more functions... */
};
And the declaration of the function :
template <class T>
template <class InputIterator>
inline typename List<T>::iterator List<T>::insert(const_iterator position, InputIterator first, InputIterator last)
{
/* i don't know how to deal with the InputIterator */
value_type a(*first); // Illegal indirection
iterator it(first); // not working
}
Any help is welcome
A little help please with this task, I need to write a simplified map template with Pair class and iterator class, I'm a beginner and I'm really messy and troubled with this, I would be glad for some help only with the header.
#include <cassert>
#include <functional>
#include "Exceptions.h"
template <typename DataType>
struct Node {
DataType data;
Node<DataType> *next;
};
namespace mtm {
template <class KeyType, class ValueType, class CompareFunction = std::less<KeyType> >
class MtmMap {
public:
class Pair {
public:
Pair(const KeyType& key, const ValueType& value)
: first(key), second(value){}
const KeyType first;
ValueType second;
~Pair() = default;
Pair* begin();
Pair* end();
void insert();
void insert(const KeyType&, const ValueType&);
void remove(const KeyType&);
bool containsKey(const KeyType& key) const;
int size() const;
Pair& operator=(const Pair&) = default;
ValueType& operator[](const KeyType&);
const ValueType& operator[](const KeyType&) const;
Pair& operator[]();
/*private:
Node<Pair> _pairs;
int _size;
*/
};
class iterator{
/*private:
Pair *cur_itr;
Node<Pair*> pair_ptr;
*/
public:
iterator();
iterator(const Pair*);
iterator(const iterator&);
~iterator();
iterator& operator=(const iterator&) = default;
iterator& operator++(int);
iterator& operator++();
iterator& operator*();
bool operator==(const iterator&);
};
bool operator!=(const iterator&, const iterator&);
};
}
I was given an empty part, like this:
#include <cassert>
#include <functional>
#include "Exceptions.h"
namespace mtm {
template <class KeyType, class ValueType, class CompareFunction = std::less<KeyType> >
class MtmMap {
public:
class Pair {
public:
Pair(const KeyType& key, const ValueType& value)
: first(key), second(value) {}
const KeyType first;
ValueType second;
};
};
}
And the first part is after I wrote all the needed for realization operators and functions. Notice that it is pretty simplified version of map container, so I only need this part, WITHOUT USING ANY STL.
Can somebody help with writing the private fields and other things that belongs to the structure of the template class MtmMap ???
The idea using a list struct is mine, as I need list of operators and pairs as a container, as I can see it.
Any other ideas, comments, and stuff will be excellent and I'll be grateful, thanks a lot.
EDIT:
Just to clarify my question, before I'll continue to the cpp file for realization, I'm stuck, because I don't understand how I should realize all the functions of the map, how to storage them and etc.
I need help finishing this header.
I have the following code:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
Iterator end();
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find();
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
template<class T>
class List<T>::Iterator
{
public:
Iterator() : list(NULL), node(NULL){} //Constructor
Iterator(const Iterator& it) : list(it.list), node(it.node) {}
~Iterator(); //Destructor
Iterator& operator=(const Iterator& it);
T& operator * ();
T& operator ++ ();
T operator ++ (int);
T& operator -- ();
T operator -- (int);
bool operator == (const Iterator& iterator) const;
bool operator != (const Iterator& iterator) const;
private:
List<T>* list;
Node* node;
};
template<class T>
class List<T>::ConstIterator
{
public:
ConstIterator() : list(NULL), node(NULL){}
ConstIterator(const ConstIterator& it) : list(it.list), node(it.node) {}
~ConstIterator(); //Destructor
ConstIterator& operator=(const ConstIterator& it);
T& operator * ();
T& operator ++ ();
T operator ++ (int);
T& operator -- ();
T operator -- (int);
bool operator == (const ConstIterator& iterator) const;
bool operator != (const ConstIterator& iterator) const;
private:
const List<T>* list;
const Node* node;
};
template<class T>
Iterator List<T>::begin() {
return Iterator(this, head);
}
When I try to compile I get the following error:
error: expected constructor, destructor, or type conversion before ‘List’
On line:
Iterator List<T>::begin() {
I'm not sure what I'm doing wrong.
Iterator is not defined, but List<T>::Iterator is. You will also need to add typename:
template<class T>
typename List<T>::Iterator List<T>::begin() { ... };
Here, typename is required as an ambiguitator to tell the compiler that List<T>::Iterator is a type (rather than a static member). This is always required in the templated context (see here).
if you write the body of the function outside the class declaration, it should be:
typename List<T>::Iterator List<T>::begin() { ... }
edit: typename added
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?