I am trying to implement Hashtable via LinkedList for collisions and I am having problem implementing copy constructor inside Hashtable (confused with the const-correctness stuff).
This is the error I am seeing:
void LinkedList<KVP<T>>::add(const KVP<T> &)' : cannot convert argument 1 from 'const int' to 'const KVP<T> &
Here is my code:
Hashtable:
#include <stdlib.h>
#include <string>
#include <vector>
#include "LinkedList.h"
#pragma once
template <typename T>
struct KVP
{
KVP() {}
KVP(const T &data, const std::string &key) : data(data), key(key) {}
const std::string key;
T data;
};
template <typename T>
class Hashtable
{
typedef KVP<T> kvp;
typedef LinkedList<kvp> list;
std::vector<list> table;
std::size_t size;
public:
Hashtable(int size) : size(size), table(size) {}
Hashtable(const Hashtable& other) : size(other.size)
{
table = other.table; //this causes problems
}
Hashtable& operator=(Hashtable other)
{
swap(*this, other);
return *this;
}
...
};
Linked List:
#include <stdlib.h>
#include <memory>
#pragma once
template <typename T>
class LinkedList;
template <typename TNode>
class LinkedListIterator
{
friend class LinkedList<typename TNode::value_type>;
TNode* p;
public:
LinkedListIterator(TNode* p) : p(p) {}
LinkedListIterator(const LinkedListIterator& other) : p(other.p) {}
LinkedListIterator& operator=(LinkedListIterator other) { std::swap(p, other.p); return *this; }
void operator++() { p = p->next; }
void operator++(int) { p = p->next; }
bool operator==(const LinkedListIterator& other) { return p == other.p; }
bool operator!=(const LinkedListIterator& other) { return !(p == other.p); }
const int& operator*() const { return p->data; }
LinkedListIterator<TNode> operator+(int i)
{
LinkedListIterator<TNode> iter = *this;
while (i-- > 0 && iter.p)
{
++iter;
}
return iter;
}
};
template <typename T>
class Node
{
friend class LinkedList<T>;
friend class LinkedListIterator<Node<T>>;
friend class LinkedListIterator<const Node<T>>;
Node() : next(nullptr) {}
Node(const T &data) : data(data), next(nullptr) {}
Node<T> *next;
T data;
public:
typedef T value_type;
};
template <typename T>
class LinkedList
{
typedef Node<T> node;
std::size_t size;
std::unique_ptr<node> head;
std::unique_ptr<node> tail;
void init()
{
size = 0;
head.reset(new node);
tail.reset(new node);
head->next = tail.get();
}
public:
typedef LinkedListIterator<node> iterator;
typedef LinkedListIterator<const node> const_iterator;
LinkedList() { init(); }
LinkedList(const LinkedList& other)
{
init();
const_iterator i = other.begin();
while (i != other.end())
{
add(*i);
i++;
}
head.reset(other.head.get());
tail.reset(other.tail.get());
}
LinkedList(LinkedList&& other)
{
size = other.size;
head = other.head;
tail = other.tail;
other.size = 0;
}
LinkedList& operator=(LinkedList other)
{
swap(*this, other);
return *this;
}
LinkedList& operator=(LinkedList&& other)
{
assert(this != &other);
while (head->next != tail)
remove(begin());
head = other.head;
tail = other.tail;
size = other.size;
other.size = 0;
return *this;
}
virtual ~LinkedList()
{
while (head->next != tail.get())
remove(begin());
}
friend void swap(LinkedList& first, LinkedList& second)
{
std::swap(first.size, second.size);
std::swap(first.head, second.head);
std::swap(first.tail, second.tail);
}
void add(const T &value)
{
node *first = new node(value);
first->next = head->next;
head->next = first;
size++;
}
void remove(iterator& removeIter)
{
node *last = head.get();
iterator i = begin();
while (i != removeIter)
{
last = i.p;
++i;
}
if (i != end())
{
last->next = i.p->next;
size--;
delete i.p;
}
}
const int getSize()
{
return size;
}
iterator begin()
{
return iterator(head->next);
}
const_iterator begin() const
{
return const_iterator(head->next);
}
iterator end()
{
return iterator(tail.get());
}
const_iterator end() const
{
return const_iterator(tail.get());
}
};
On its own LinkedList copy ctor seems to work, e.g. this compiles:
LinkedList<int> list;
LinkedList<int> list2;
list2 = list;
But this doesn't:
Hashtable<int> table1(50);
Hashtable<int> table2 = table1;
edit: Also if I define table with a pointer:
std::vector<list*> table;
it works, but I don't think this is best way.
Your LinkedListIterator<const Node<T>>::operator* returns const int&, rather than the value type of the LinkedList<T>. Your LinkedList<int> test passed because the template parameter happened to match the hard-coded return type of operator*.
Related
Code below, for my linked list implementation and specifically emplace_back below. What am I doing wrong and how to fix?
Error I am getting is:
Build started...
1>------ Build started: Project: so_list_emplace, Configuration: Debug Win32 ------
1>main.cpp
1list.hpp(191,19): error C2280: 'list<President>::node::node(void)': attempting to reference a deleted function
1>list.hpp(15): message : compiler has generated 'list<President>::node::node' here
1>list.hpp(15,1): message : 'list<President>::node::node(void)': function was implicitly deleted because a data member 'list<President>::node::value' has either no appropriate default constructor or overload resolution was ambiguous
1>list.hpp(12): message : see declaration of 'list<President>::node::value'
1>main.cpp(29): message : see reference to function template instantiation 'void list<President>::emplace_back<const char(&)[15],const char(&)[13],int>(const char (&)[15],const char (&)[13],int &&)' being compiled
1>main.cpp(29): message : see reference to function template instantiation 'void list<President>::emplace_back<const char(&)[15],const char(&)[13],int>(const char (&)[15],const char (&)[13],int &&)' being compiled
1>list.hpp(192,10): error C2679: binary '=': no operator found which takes a right-hand operand of type 'T *' (or there is no acceptable conversion)
1> with
1> [
1> T=President
1> ]
1>main.cpp(22,13): message : could be 'President &President::operator =(const President &)'
1>list.hpp(190,1): message : while trying to match the argument list '(T, T *)'
1> with
1> [
1> T=President
1> ]
1>Done building project "so_list_emplace.vcxproj" -- FAILED.
list.hpp implementation:
#ifndef LIST_HPP_
#define LIST_HPP_
#include <cstddef>
#include <initializer_list>
#include <utility>
template< typename T >
class list {
public:
struct node {
T value;
node* next;
node* prior;
};
struct iterator {
iterator(node* nod) : ptr_(nod) {}
iterator& operator++() {
if (ptr_) {
ptr_ = ptr_->next;
}
return *this;
}
iterator operator++(T) {
auto old = *this;
if (ptr_) {
ptr_ = ptr_->next;
}
return old;
}
T& operator*() const { return ptr_->value; }
T* operator->() { return &ptr_->value; }
bool operator==(const iterator& other) { return ptr_ == other.ptr_; }
bool operator!=(const iterator& other) { return ptr_ != other.ptr_; }
node* ptr_;
};
list() : head_(nullptr), tail_(nullptr), size_(0) {}
// O(n)
template< typename input_iterator >
list(input_iterator first, input_iterator last) : head_(nullptr), tail_(nullptr), size_(0) {
for (auto it = first; it != last; ++it) {
push_back(*it);
}
}
// O(n)
list(std::initializer_list<T> init) : list<T>(init.begin(), init.end()) {}
// O(n)
list(const list& other) : head_(nullptr), tail_(nullptr), size_(0) {
auto it = other.begin();
while (it != nullptr) {
push_back(*it);
++it;
}
size_ = other.size();
}
// O(n)
list& operator=(const list& other) {
if (this != &other) {
clear();
auto it = other.begin();
while (it != nullptr) {
push_back(*it);
++it;
}
size_ = other.size();
}
return *this;
}
list(list&& other) : head_(other.head_), tail_(other.tail_), size_(other.size()) {
other.size_ = 0;
other.head_ = nullptr;
other.tail_ = nullptr;
}
list& operator=(list&& other) {
head_ = other.head_;
tail_ = other.tail_;
size_ = other.size();
other.clear();
other.head_ = nullptr;
other.tail_ = nullptr;
other.size_ = 0;
}
// O(n)
~list() {
clear();
}
// O(n)
void clear() {
if (head_) {
node* current = head_;
while (current) {
node* next = current->next;
delete current;
current = next;
}
}
head_ = nullptr;
tail_ = nullptr;
size_ = 0;
}
// O(1)
bool empty() const {
return head_ == nullptr;
}
// O(1)
void push_back(const T& value) {
node* newnode = make_node(value);
if (tail_) {
node* oldtail = tail_;
oldtail->next = newnode;
newnode->prior = oldtail;
tail_ = newnode;
}
else {
head_ = tail_ = newnode;
}
++size_;
}
// O(1)
size_t size() const {
return size_;
}
iterator begin() {
return iterator(head_);
}
const iterator begin() const {
return iterator(head_);
}
iterator end() {
return nullptr;
}
const iterator end() const {
return nullptr;
}
// O(1)
T& front() { return *iterator(head_); }
const T& front() const { return *iterator(head_); }
// O(1)
T& back() { return *iterator(tail_); }
const T& back() const { return *iterator(tail_); }
// O(1)
void pop_back() {
if (tail_) {
node* newtail = tail_->prior;
if (newtail) {
newtail->next = nullptr;
}
else {
// means that head_ has also been erased
head_ = nullptr;
}
delete tail_;
tail_ = newtail;
--size_;
}
}
template<typename... P>
void emplace_back(P&&... v)
{
node* newnode = new node;
newnode->value = new T(std::forward<P>(v)...);
newnode->next = nullptr;
newnode->prior = nullptr;
if (tail_) {
node* oldtail = tail_;
oldtail->next = newnode;
newnode->prior = oldtail;
tail_ = newnode;
}
else {
head_ = tail_ = newnode;
}
++size_;
}
private:
node* make_node(const T& value) {
node* newnode = new node;
newnode->value = value;
newnode->next = nullptr;
newnode->prior = nullptr;
return newnode;
}
node* head_;
node* tail_;
size_t size_;
};
#endif // LIST_HPP_
main.cpp to exercise:
#include "list.hpp"
#include <iostream>
#include <string>
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other) = default;
};
int main() {
list<President> elections;
elections.emplace_back("Nelson Mandela", "South Africa", 1994);
}
Your issue is that node is trying to construct a President, but President doesn't have a default constructor. You'll need to construct a node with a President, like in this constructor:
node(T const &v) : value(v) { }
Because emplace_back tries to construct an object in place, you'll also need to add a constructor to construct value using the arguments that are passed in.
template <typename ...Args>
node(Args &&...v) : value(std::forward<Args>(v)...) { }
Lastly, update your emplace_back function to forward arguments at construction time.
node* newnode = new node(std::forward<P>(v)...);
This is compiling for me with gcc and clang.
The problems(as reflected in the errors) are:
There is no default constructor for list::node::node() because it is implicitly deleted.
President has no default constructor because you've user defined constructors for President and so compiler will not synthesize the default constructor for you.
There is no operator= for President.
To solve these problems you need to add the following things:
Default constructor for node like node() = default(); inside node.
Default constructor for President like President() = default; inside President.
Define(overload) the assignment operator for President.
I have this code below, and I am having a hard time getting it to work (operators in the movable_ptr<T> class, to be precise).
//movable_ptr.hpp
//Michal Cermak
#ifndef MOVABLE_H
#define MOVABLE_H
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() : ptr_(nullptr) {};
enable_movable_ptr(T* p) : ptr_(p) {};
//copy
enable_movable_ptr(const enable_movable_ptr<T>&) {};
enable_movable_ptr& operator=(const enable_movable_ptr<T>& p) {
T* new_ptr = p.first_;
movable_ptr<T>* new_first = p.first_;
delete p;
ptr_ = new_ptr;
first_ = new_first;
return this;
};
//move
enable_movable_ptr(enable_movable_ptr<T>&& p) {};
enable_movable_ptr& operator=(enable_movable_ptr<T>&& p) {};
//destructor
~enable_movable_ptr() {delete ptr_; };
T* get() {return ptr_; };
movable_ptr<T>* getFirst() { return first_; };
void setFirst(movable_ptr<T>* p) { first_ = p; };
private:
T* ptr_ = nullptr;
movable_ptr<T>* first_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//parameterless constructor
movable_ptr() {};
//constructor from T*
movable_ptr(T* p) : ptr_(p) { add_to_tracked(this); };
//copy
movable_ptr(const enable_movable_ptr<T>&) {};
movable_ptr& operator=(const enable_movable_ptr<T>& p) {};
//move
movable_ptr(enable_movable_ptr<T>&& p) {};
movable_ptr& operator=(enable_movable_ptr<T>&& p) {};
//destructor
~movable_ptr() {};
//operators
T& operator*() const { return ptr_; };
T* operator->() const { return ptr_; };
explicit operator bool() const noexcept { return ptr_ != nullptr; };
bool operator!() const { return ptr_ == nullptr; };
bool operator==(const movable_ptr<T>& p) const { return p.get() == ptr_; };
bool operator!=(const movable_ptr<T>& p) const { return p.get() != ptr_; };
//reset
void reset() noexcept { ptr_, next_, prev_ = nullptr; };
template<typename X> void reset(X* p) { remove_from_tracked(this); ptr_ = p; add_to_tracked(this); };
//access to variables
enable_movable_ptr<T>* get() {return ptr_; };
movable_ptr<T>* getNext() { return next_; };
void setNext(movable_ptr<T>* p) { next_ = p; };
movable_ptr<T>* getPrevious() {return prev_; };
void setPrevious(movable_ptr<T>* p) { prev_ = p; };
//get_movable
movable_ptr<T>* get_movable(enable_movable_ptr<T>& p) {};
private:
enable_movable_ptr<T>* ptr_ = nullptr;
movable_ptr<T>* next_ = nullptr;
movable_ptr<T>* prev_ = nullptr;
};
template<typename T> movable_ptr<T> get_movable(enable_movable_ptr<T>& p){
return new movable_ptr<p>(p);
};
//removes movable_ptr from tracked pointers
template<typename T> void remove_from_tracked(movable_ptr<T>* p) {
movable_ptr<T>* first = p->get()->getFirst();
movable_ptr<T>* prev = p->get()->getFirst()->getPrevious();
movable_ptr<T>* next = p->get()->getFirst()->getNext();
if (first == p && next != nullptr)
{
p->get()->setFirst(next);
}
if (prev != next)
{
next->setPrevious(prev);
prev->setNext(next);
}
else
{
next->setPrevious(nullptr);
prev->setNext(nullptr);
}
};
//adds movable_ptr to tracked pointers
template<typename T> void add_to_tracked(movable_ptr<T>* p) {
movable_ptr<T>* first = p->get()->getFirst();
movable_ptr<T>* prev = p->get()->getFirst()->getPrevious();
if (first != nullptr)
{
if (prev != nullptr) {
prev->setNext(p);
}
first->setPrevious(p);
}
p->get()->setFirst(p);
};
#endif
#include <memory>
#include <array>
#include "movable_ptr.hpp"
class MovableNode : public enable_movable_ptr<MovableNode>
{
public:
static const int MAX_REFS = 4;
using RefArray = std::array<movable_ptr<MovableNode>, MAX_REFS>;
MovableNode() : _isValid(false), _value(0), _refs() {}
MovableNode(int value) : _isValid(true), _value(value), _refs() {}
bool isValid() const { return _isValid; }
int value() const { checkValid(); return _value; }
RefArray& refs() { checkValid(); return _refs; }
private:
bool _isValid;
int _value;
RefArray _refs;
void checkValid() const;
};
The trouble is, the compiler is unable to convert the ptr_ variable to the correct return type in operator*. operator== and operator!= are in a similar situation, but this time it is the p.get() that cannot be converted from const movable_ptr<T> to movable_ptr<T> &, so that it can be properly compared.
Errors:
Error C2440 'return': cannot convert from 'enable_movable_ptr<MovableNode> *const ' to 'T &'
Error C2662 'enable_movable_ptr<A> *movable_ptr<T>::get(void)': cannot convert 'this' pointer from 'const movable_ptr<T>' to 'movable_ptr<T> &'
I am pretty sure I am just missing a minor detail, but how would I go about solving this?
Code that instantiates the classes:
#include <iostream>
#include <memory>
#include <string>
#include "movable_ptr.hpp"
using namespace std;
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
void test_ptr_dereference() {
A x(42);
auto px = get_movable(x);
TEST_ASSERT(&*px == &x);
TEST_ASSERT(&px->val == &x.val);
}
int main(int argc, char* argv[]) {
test_ptr_dereference();
}
Got this error messege on an attempt to return the data from an Item template under iterator class.
I don't understand why Im getting an error (C++)..
template<class E>
class Item {
Item<E>* next;
E data;
public:
Item() :next(NULL) {}
Item(const E& pdata) :next(NULL), data(pdata) {}
void setNext(Item<E>& next) { this->next = next; }
Item<E>& getNext() { return next; }
void setData(const E pdata) { this->data = data; }
E& getData() { return data; }
};
this is the iterator class:
class Iterator {
Item<T>* p;
public:
Iterator(Item<T>* pt = NULL) :p(pt) {}
Iterator& operator++(int) {
p = p->getNext();
return *this;
}
T& operator*() { return *(p->getData()); }
friend class RoundList<T>;
};
they're both under a template class that called RoundList (template )
help...?
This is the code I tested.
template <class E>
class Item {
Item<E>* next;
E data;
public:
Item() :next(NULL) {}
Item(const E& pdata) :next(NULL), data(pdata) {}
void setNext(Item<E>& next) { this->next = next; }
Item<E>& getNext() { return next; }
void setData(const E pdata) { this->data = pdata; }
E& getData() { return data; }
};
template <class T>
class Iterator {
Item<T>* p;
public:
Iterator(Item<T>* pt = NULL) :p(pt) {}
Iterator& operator++(int) {
p = p->getNext();
return *this;
}
T& operator*() { return p->getData(); }
};
int main()
{
Item<int>* test = new Item<int>();
Iterator<int>* iterTest = new Iterator<int>(test);
test->setData(2);
cout << iterTest->operator*() << endl;
cout << (test->getData() = 4) << endl;
}
I'm not sure how you want to use your Iterator, but I tried with a simple type, like int and it works. Anyway I change your *(p->getData()) in p->getData() since in getData you are already returning a reference.
Okay, So I've been working on some book examples and stuff and found this exercise to implement the STL List lookalike. I've made it somehow and it kinda works, but I've got some major flaws in the implementation. The biggest one is that I have totally no idea how to make my List.end() iterator to work as it's supposed to do.
I guess I'll show the code first and try to tell some of my ideas next.
#ifndef TESTS_LST_H
#define TESTS_LST_H
#include <memory>
#include <cstddef>
template<class T> class Node;
template<class T> class ListIter;
template<class T>
class List {
public:
typedef ListIter<T> iterator;
typedef const ListIter<T> const_iterator;
typedef std::size_t size_type;
List(): first(0), last(0), sz(0) {}
List(const List<T>& lst);
~List() { clear(); }
iterator begin() { return iterator(first); }
iterator end() { return iterator(last); }
iterator insert() {}
iterator erase() {}
const_iterator begin() const { return iterator(first); }
const_iterator end() const { return iterator(last); }
void push_back(const T& val);
void push_front(const T& val);
void clear();
void pop_front();
void pop_back();
size_type size() { return sz; }
bool empty() { return sz == 0; }
List& operator=(const List& l);
private:
Node<T>* first;
Node<T>* last;
size_type sz;
std::allocator<Node<T>>* alloc;
};
template<class T>
class Node {
public:
Node(): next(0), prev(0), value(0) {}
Node(const T& val): next(0), prev(0), value(val) {}
private:
Node<T>* next;
Node<T>* prev;
T value;
friend class List<T>;
friend class ListIter<T>;
};
template<class T>
class ListIter {
public:
typedef ListIter<T> iterator;
ListIter(Node<T>* iter): current_node(iter) {}
ListIter(): current_node(0) {}
ListIter(ListIter<T>* iter): current_node(iter->current_node) {}
inline T& operator*() { return current_node->value; }
iterator& operator=(const iterator& rhs) { *this->current_node = rhs.current_node; }
bool operator==(const iterator& rhs) { return current_node->value == rhs.current_node->value; }
bool operator!=(const iterator& rhs) { return current_node->value != rhs.current_node->value; }
iterator& operator++();
iterator operator++(int);
iterator& operator--();
iterator operator--(int);
private:
Node<T>* current_node;
friend class List<T>;
};
template<class T>
void List<T>::push_back(const T& val)
{
Node<T>* temp = alloc->allocate(1);
alloc->construct(temp, val);
if (first == 0) {
first = last = temp;
} else {
temp->prev = last;
last->next = temp;
last = temp;
}
sz++;
}
template<class T>
void List<T>::push_front(const T &val)
{
Node<T>* temp = alloc->allocate(1);
alloc->construct(temp, val);
if (first == 0) {
first = last = temp;
} else {
temp->prev = 0;
temp->next = first;
first->prev = temp;
first = temp;
}
sz++;
}
template<class T>
void List<T>::clear()
{
Node<T>* current = first;
while (current != 0) {
Node<T>* next = current->next;
//delete current
alloc->deallocate(current, 1);
alloc->destroy(current);
current = next;
}
first = last = 0;
sz = 0;
}
template<class T>
List<T>::List(const List &lst)
{
first = last = 0;
sz = 0;
for (auto it = lst.begin(); it != lst.end(); it++) {
push_back(it.current_node->value);
}
push_back(lst.last->value);
}
template<class T>
List<T>& List<T>::operator=(const List &lst)
{
first = last = 0;
sz = 0;
for (auto it = lst.begin(); it != lst.end(); ++it) {
push_back(it.current_node->value);
}
push_back(lst.last->value);
return *this;
}
template<class T>
void List<T>::pop_front()
{
first = first->next;
alloc->deallocate(first->prev, 1);
alloc->destroy(first->prev);
first->prev = 0;
sz--;
}
template<class T>
void List<T>::pop_back()
{
last = last->prev;
alloc->deallocate(last->next, 1);
alloc->destroy(last->next);
last->next = 0;
sz--;
}
template<class T>
ListIter<T>& ListIter<T>::operator++()
{
current_node = current_node->next;
return *this;
}
template<class T>
ListIter<T>& ListIter<T>::operator--()
{
current_node = current_node->prev;
return *this;
}
template<class T>
ListIter<T> ListIter<T>::operator++(int)
{
iterator tmp(*this);
++*this;
return tmp;
}
template<class T>
ListIter<T> ListIter<T>::operator--(int)
{
iterator tmp(*this);
--*this;
return tmp;
}
#endif //TESTS_LST_H
As you can see .end() function returns a regular last element of the list and not the one past the end as it should. Should I try to rework this part to possibly keep the *last as the one past the end iterator and use the operator+ to iterate through the list to omit the need in the pointer to the end of the actual list?
Something like this (not sure about the corectness of the code below):
iterator& operator+(std::size_type n)
{
for (auto i = 0; i < n; ++i) {
++*this;
}
return *this;
}
But I'm not sure that's how the stuff works in the actual implementation, loops could be very demanding after all.
I know that this stuff is already out there and works and all that. That's just for the educational purposes, so I hope to hear some ideas. Thanks in advance.
Iterator were known in the past as "smart pointer", since they works like that. (Indeed, pointers are iterators, but not the opposed). So, think an iterator like a pointer.
"One past the end" is clear what means when you are working with vectors: a vector contains its elements in contiguous space. Indeed, it is possible to implement vector iterator with just pointers. But that is not the case for a linked list, where generally its element are not in contiguous memory.
Because you implemented the List class as a doubled linked list, I suggest you to change the first and last pointers by a head:
template<class T>
class List {
// ...
private:
Node<T> head;
size_type sz;
};
So, the begin() iterator become head.next and end() iterator become &head. This works as far the last element in the list points to the head.
BTW: You don't need to create Node<T> as a class with friends classes. It is just an implementation detail. Change it to a struct and put it in a implementation namespace.
I am looking for what's wrong in this custom double linkedlist homework assignment. It is not finished because I haven't sorted out the errors. I went through this code line by line with my tutor and he says it's correct, yet it displays errors.
We've tried viewing the whitespace, changing public to private + vice versa, adding/removing semicolons throughout the code, checking the text encoding. I don't need help with the actual linkedlist itself, just why I'm getting all these errors.
We must use nested class and must all be in one file The errors I am getting vary from 0 - 40 in number.
#pragma once
#include <initializer_list>
#include <iostream>
#include <cstdlib>
//#include "Node.h"
//#include "Iterator.h"
template <typename T>
class DoublyLinkedList <T>
{
public:
class Node
{
private:
T data;
Node *next;
Node *prev;
public:
Node(const T & d, Node * p = nullptr, Node * n = nullptr) : data(d), next(n), prev(p) {}
};
Node *head;
Node *tail;
class Iterator
{
private:
Node *current;
bool reversed;
public:
Iterator(Node * n = head, bool rev = false) : current(n), reversed(rev) {}
Iterator& operator--()
{
if (reversed)
current = current->next;
else
current = current->prev;
return *this;
}
Iterator& operator++()
{
if (reversed)
{
current = current->prev;
}
else
{
current = current->next;
}
return *this;
}
const T& operator *() const
{
return *current;
}
bool operator!=(const Iterator& other) const
{
return (this->current != other->current);
}
bool operator==(const Iterator& other) const
{
return (this->current == other->current);
}
Iterator begin()
{
current = head;
}
Iterator end()
{
current = tail;
}
Iterator rbegin()
{
current = tail;
}
Iterator rend()
{
current = head;
}
};
DoublyLinkedList():head(nullptr), tail(nullptr)
{
}
//
DoublyLinkedList(const DoublyLinkedList& other)
{
for (auto x : other)
push_back(x);
}
//
DoublyLinkedList(initializer_list<T> & list)
{
}
size_t size() const noexcept
{
for (size_t length = 0, iterator iter = iterator::begin(); iter != nullptr; ++iter, ++length) { return length; }
}
void push_back(const T& value)
{
Node * newLast = new Node(value, nullptr, tail);
tail = newLast;
}
void erase(Iterator iter)
{
delete * iter;
}
void remove(const T& val)
{
Iterator iter = Iterator::begin();
while (*iter != nullptr)
{
if (*iter == val)
delete *iter;
else
++iter;
}
}
//
void insert(Iterator iter, const T& value)
{
}
};
class DoublyLinkedList <T>
// ^^^
is wrong in the class declaration. Just omit the <T>:
template <typename T>
class DoublyLinkedList // <<<<< No <T>
{
// ...
};
How about removing <T> at the end of class DoublyLinkedList <T> ?