I'm not sure how much this fits in here and I'm kinda new to C++ but I have to make an ADT over a dynamic array/linked list with iterators. My question is, is there a way to make this iterator a template so it could work for both the dynamic array and the linked list or I have to make 2 different implementations for a class Iterator?
I was thinking of something like this:
template<typename Container>
class Iterator {
private:
Container *cont;
int pos;
public:
Iterator();
Iterator(const Container& c);
~Iterator();
bool isValid();
void operator++();
void operator--();
Element getCurrent();
};
Now clearly, it has no idea what Element is and that's my problem. Is there any way to have getCurrent() to return the element from the current position?
Is this going anywhere?
in c++ 14 you can do this :
template<typename Container>
class Iterator {
private:
Container *cont;
int pos;
public:
Iterator();
Iterator(const Container& c);
~Iterator();
bool isValid();
void operator++();
void operator--();
auto getCurrent(); // the return type is automatically generated
};
but in c++11
you have to erase the return type
so getCurrent(); must return a void *
and use reinterpret_cast(getCurrent());
implementation correction: (what i think)
template<typename Container>
class Iterator {
private:
Container *cont;
int currentPos;
int beginPos;
int endPos;
public:
Iterator();
Iterator(const Container& c,int endpos)currentPos{0},beginPos{0},endPos{endpos};
~Iterator();
void operator++();
void operator--();
auto& getCurrent()const;
}
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 have an assignment in which I need to make template classes LinkedList and Traversible. Class Traversible needs to be a interface which declares functions for indexing and iteration of some collection class. I don't exactly know how to make an interface for iterator so LinkedList can use it. I was thinking something like
template <class T, class U>
class ITraversible {
public:
virtual U begin() noexcept = 0;
virtual U end() noexcept = 0;
virtual T& operator[](int) = 0;
};
and then in LinkedList header file I would do:
template <class T>
class LinkedList : public ITraversible<T,typename LinkedList<T>::iterator> {
struct node {
T data;
node* next, *prev;
explicit node(const T&);
void connect(node*);
};
node *head, *tail;
int n;
public:
/*************************ITERATOR************************/
class iterator : public std::iterator<std::bidirectional_iterator_tag, node*> {
typename LinkedList<T>::node* itr;
explicit iterator(node*) noexcept;
friend class LinkedList;
public:
iterator& operator++();
iterator operator++(int);
iterator& operator--();
iterator operator--(int);
bool operator==(const iterator&) const noexcept;
bool operator!=(const iterator&) const noexcept;
T& operator*() const noexcept;
T& operator->() const noexcept;
};
/**********************************************************/
LinkedList() noexcept;
LinkedList(std::initializer_list<T>);
LinkedList(const LinkedList&);
LinkedList(LinkedList&&) noexcept;
~LinkedList() noexcept;
LinkedList& operator=(LinkedList) noexcept;
template <class A>
friend void swap(LinkedList<A>&, LinkedList<A>&);
void add(const T&);
void removeAt(int);
int size() const noexcept;
bool operator==(const LinkedList&) const noexcept;
bool operator!=(const LinkedList&) const noexcept;
virtual T& operator[](int) override;
virtual iterator begin() noexcept override;
virtual iterator end() noexcept override;
};
But then Traversable template has two parameters and it should have only one.
Is this what I am supposed to do? Keep in mind I am new to templates and iterators.
When creating an interface you'll need to nail down the static types of what is being returned. These may behave dynamically different but you can't change the type other than using a subtype relation when returning pointers or references.
Personally, I think this exercise is ill-advised for a C++ context. It may make some sense when using Java or C#. However, similar behavior can be obtained. A rought sketch would be something like this (although this should work it will be rather slow):
template <typename T>
struct iterator_base {
virtual iterator_base() {}
virtual iterator_base<T>* do_clone() = 0;
virtual T& do_value() = 0;
virtual void do_next() = 0;
virtual bool do_equal() = 0;
// other operations to implement operator--, operator[], ...
};
template <typename It>
class iterator: iterator_base<typename std::iterator_traits<It>::value_type> {
typedef typename std::iterator_traits<It>::value_type> type;
It it;
iterator_base<type>* do_clone() { return new iterator<It>(*this); }
type& do_value() { return *this->it; }
void do_next() { ++this->it; }
bool do_equal(iterator_base<type>* other) {
return this->it == static_cast<iterator<It>>(other)->it;
}
};
template <typename T>
class poly_iterator {
std::unique_ptr<iterator_base<T>> ptr;
public:
poly_iterator(iterator_base<T>* ptr): ptr(ptr) {}
poly_iterator(poly_iterator const& other): ptr(other.ptr->clone()) {}
poly_iterator& operator= (poly_iterator other) {
other.swap(this);
return *this;
}
void swap(poly_iterator& other) { swap(this->ptr, other.ptr); }
T& operator*() { return this->ptr->value(); }
T* operator->() { return &this->operator*(); }
poly_iterator& operator++() { this->ptr->next(); return *this; }
poly_iterator operator++(int) {
poly_iterator rc(*this);
this->operator++();
return rc;
}
bool operator== (poly_iterator const& other) {
return this->ptr->equal(other.ptr.ptr());
}
bool operator!= (poly_iterator const& other) {
return !(*this == other);
}
// other operations
};
// define a suitable specialization of std::iterator_traits<poly_iterator<T>>
template <typename T>
class ITraversible {
virtual iterator_base<T>* do_begin() = 0;
virutal iterator_base<T>* do_end() = 0;
public:
poly_iterator<T> begin() { return this->do_begin(); }
poly_iterator<T> end() { return this->do_end(); }
// other operations
};
template <typename T>
class List: public ITraversible<T> {
std::list<T> list;
iterator_base<T>* do_begin() {
return iterator<std::list<T>::iterator>(list.begin());
}
iterator_base<T>* do_end() {
return iterator<std::list<T>::iterator>(list.end());
}
public:
// whatever is needed to fill the list
};
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
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.
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?