I’m working on a linked list class which provides iteration support.
template <typename T>
class list
{
private:
struct node { T data; node *next; } *m_head = nullptr, *m_tail = nullptr;
std::size_t m_count = 0ULL;
public:
class const_iterator
{
private:
node *curr = nullptr, *prev = nullptr;
const_iterator(node *prev, node *curr) : prev(prev), curr(curr) {}
public:
const_iterator(void) = default;
const_iterator next(void) const
{ return const_iterator(curr ? curr : prev, curr ? curr->next : nullptr); }
const T &operator*(void) const
{ return curr->data; }
bool operator==(const const_iterator &rvalue) const
{ return curr == rvalue.curr; }
bool operator!=(const const_iterator &rvalue) const
{ return curr != rvalue.curr; }
const_iterator operator+(std::size_t offset) const;
const_iterator &operator++(void);
const_iterator operator++(int);
friend class list;
};
class iterator
{
private:
node *curr = nullptr, *prev = nullptr;
iterator(node *prev, node *curr) : prev(prev), curr(curr) {}
public:
iterator(void) = default;
iterator next(void) const
{ return iterator(curr ? curr : prev, curr ? curr->next : nullptr); }
T &operator*(void)
{ return curr->data; }
bool operator==(const iterator &rvalue) const
{ return curr == rvalue.curr; }
bool operator!=(const iterator &rvalue) const
{ return curr != rvalue.curr; }
iterator operator+(std::size_t offset) const;
iterator &operator++(void);
iterator operator++(int);
friend class list;
};
list(void) = default;
list(std::initializer_list<T> init)
{ for (const T &value: init) enqueue(value); }
list(const list<T> &init)
{ for (const T &value: init) enqueue(value); }
// ~list(void) { while (m_count) pop(); }
const_iterator begin(void) const
{ return const_iterator(nullptr, m_head); }
iterator begin(void)
{ return iterator(nullptr, m_head); }
std::size_t count(void) const
{ return m_count; }
bool empty(void) const
{ return !m_count; }
const_iterator end(void) const
{ return const_iterator(m_tail, nullptr); }
iterator end(void)
{ return iterator(m_tail, nullptr); }
T head(void) const
{ return m_head->data; }
list<T> &insert(const iterator &pos, const T &data);
T tail(void) const
{ return m_tail->data; }
/* Many more methods */
};
In the implementation of the method insert
I’m using an iterator to mark the position to which I want to add data
template <typename T>
inline list<T> &list<T>::insert(const iterator &pos, const T &data)
{
node *new_node = new node {data, pos.curr};
if (empty()) m_head = m_tail = new_node;
else if (pos == begin()) m_head = new_node;
else if (pos == end()) m_tail = m_tail->next = new_node;
else pos.prev->next = new_node;
m_count++;
return *this;
}
Executing this snippet:
#include <iostream>
#include "headers/list.hpp"
int main()
{
list<int> a;
a.insert(a.begin(), 5);
a.insert(a.begin(), 7);
a.insert(a.end(), 9);
a.insert(a.begin() + 2, 1);
for (int x: a) std::cout << x << 't';
}
Locks the control on the line else pos.prev->next = new_node
. Even adding a breakpoint at that line doesn’t change anything. Why is that? Is it because I declared pos
as a constant reference and I’m trying to modify the value it points to by dereferencing the member pointer prev
? If that’s so why didn’t the compiler stop me from doing that?
I expected it to print an output like this:
7 5 1 9
I even tried to change the else statement block with some dummy useless code but it doesn’t execute either.
else for (iterator it = begin(); it != end(); it++);
LukeLikesPizza is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.