illeagal indirection error in iterator class - c++

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.

Related

I looking for advice on whether it's better to use a friend or write a getter, but (sort of) break the encapsulation?

i have a class:
template <typename T>
class List {
private:
struct pointNode {
T data;
pointNode* next;
pointNode* prev;
pointNode() :data(0), next(nullptr), prev(nullptr) {}
pointNode(T n_data) : data(n_data), next(nullptr), prev(nullptr) {}
const T& getValue() {
return this->data;
}
};
pointNode* head;
pointNode* tail;
public:
class Iterator {
//friend class List;
using Iterator_type = List<T>::pointNode;
public:
Iterator(Iterator_type* rNode) {
current_node = rNode;
}
bool operator !=(const Iterator& pNode) {
return this->current_node != pNode.current_node;
}
T const get_value() {
return this->current_node->data;
}
private:
Iterator_type* current_node;
};
List() : head(nullptr), tail(nullptr) {}
inline void InsertFront(T&& val);
inline void InsertBack(T&& val);
inline bool is_empty();
inline void Insert_after_v(T&&searchVal,T&&val);
inline void Insert_after_p(int pos, T&& val);
};
I'm trying to write a function that inserts an element after a given:
template<typename T>
inline void List<T>::Insert_after(Iterator pos, T&& val)
{
pointNode* new_node = new pointNode(std::move(val), ... );
}
as the 2 parameters of the constructor pointNode,i need to get the value of the iterator
private:
Iterator_type* current_node;
And I think it's the right thing to do ?make a friend:
struct pointNode {
friend class Iterator
But I often see that friend is not a particularly good style.
class Iterator
{
public:
Iterator_type* get_current_node() const {
return current_node;
}
or write something like this :
class Iterator
{
public:
Iterator_type* get_node() const {
return current_node;
}
But it seems to me that it is not very good to let the user get private data.So maybe who knows how to do the right thing in such situations?I would be grateful for your advice

How to properly use template class with an abstract pointer type

I created a List with a template Node class to hold different data types such as Node<int> but also more complex types such as Node<BaseEvent*>.
I also have an event container class to hold different event objects so it has a member argument
List<BaseEvent*> events;
where BaseEvent is an abstract class with derived classes that are not abstract.
In the event container I have a method called "add" (see below) that adds a new event to that events.
BaseEvent* eventClone = event.clone();
The clone returns a pointer to a new derived object such as:
new OpenEvent(*this);
Once it calls the list's insert method, it instantiates a new Node (see below), and in the Node constructor it assigns the value like so:
value(new T(new_value))
So basically it allocates a pointer memory (T=BaseEvent*).
I think I might be losing the eventClone pointer and have a memory leak.
The problem is that when I debugged it I saw that both: T* value; (aka BaseEvent** value) and BaseEvent* eventClone have the same address in memory.
I'm not sure if when I do delete value in the destructor of Node it will just free the pointer allocation to BaseEvent* or also the data that it holds.
Any insights are welcome!
Relevant code snippets
Node<T>
template <class T>
class Node
{
public:
Node(const T& new_value, Node* new_next = NULL, Node* new_prev = NULL);
~Node();
const T& getValue() const;
Node<T>* getNext() const;
Node<T>* getPrev() const;
void setNext(Node* node);
void setPrev(Node* node);
private:
T* value;
Node* next;
Node* prev;
};
template <class T>
Node<T>::Node(const T& new_value, Node* new_next, Node* new_prev) :
value(new T(new_value))
{
next = new_next;
prev = new_prev;
}
template <class T>
Node<T>::~Node()
{
delete value;
}
...
Linked list that uses Node<T>
template <class T>
class List
{
public:
List();
~List();
int getSize() const;
Node<T>* getFirst() const;
Node<T>* getNext(Node<T>& node) const;
Node<T>* getPrev(Node<T>& node) const;
void insertStart(const T& data);
void insertLast(const T& data);
void insertAfter(Node<T>& target, const T& data);
void insertBefore(Node<T>& target, const T& data);
void removeNode(Node<T>& node);
bool contains(const T data);
private:
Node<T>* head;
int size;
};
template <class T>
List<T>::List() : head(NULL), size(0)
{
}
template <class T>
List<T>::~List()
{
Node<T>* temp;
while (head)
{
temp = head;
head = head->getNext();
delete temp;
size--;
}
}
...
template <class T>
void List<T>::insertStart(const T& data) {
if (size == 0)
{
head = new Node<T>(data);
}
else
{
Node<T>* temp = new Node<T>(data, head);
head->setPrev(temp);
head = temp;
}
size++;
}
...
The event container class:
class EventContainer
{
public:
EventContainer() :
events(List<BaseEvent*>()) {}
~EventContainer() {}
virtual void add(const BaseEvent&);
class EventIterator
{
public:
EventIterator() :
current(NULL) {}
EventIterator(Node<BaseEvent*>& node) :
current(&node) {}
EventIterator(Node<BaseEvent*>* node) :
current(node) {}
~EventIterator() {}
EventIterator& operator=(const EventIterator& nodeIterator) {
current = nodeIterator.current;
return *this;
}
EventIterator& operator++() {
current = current->getNext();
return *this;
}
BaseEvent& operator*() const {
return *(current->getValue());
}
friend bool operator==(const EventIterator& iterator1, const EventIterator& iterator2) {
return iterator1.current == iterator2.current;
}
bool operator!=(const EventIterator& iterator) const {
return !(*this == iterator);
}
private:
Node<BaseEvent*>* current;
};
virtual EventIterator begin() const;
virtual EventIterator end() const;
private:
List<BaseEvent*> events;
};
The implementation of add method:
void EventContainer::add(const BaseEvent& event) {
BaseEvent* eventClone = event.clone();
if (events.getSize() == 0)
{
events.insertStart(eventClone);
return;
}
Node<BaseEvent*>* current = events.getFirst();
while (current != NULL)
{
if (*eventClone < *(current->getValue()))
{
events.insertBefore(*current, eventClone);
return;
}
current = current->getNext();
}
events.insertLast(eventClone);
}
EventContainer::EventIterator EventContainer::begin() const {
return events.getFirst();
}
EventContainer::EventIterator EventContainer::end() const {
return NULL;
}

Return cannot convert

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();
}

A tutor could not figure out why this small code is giving so many errors, please assist

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> ?

Copy constructor with vector with custom class not working?

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*.