C++ Iterator: no appropriate default constructor available - c++

I am trying to implement Linked List with custom iterator.
I am getting a bunch of errors trying to implement copy constructor:
'LinkedListIterator>' : no appropriate default constructor available
'LinkedListIterator> LinkedList::begin(void)' : cannot convert 'this' pointer rom 'const LinkedList' to 'LinkedList &'
'LinkedListIterator> LinkedList::end(void)' : cannot convert 'this' pointer from 'const LinkedList' to 'LinkedList &'
LinkedList
class LinkedList
{
std::unique_ptr<node> head;
std::unique_ptr<node> tail;
LinkedList(const LinkedList& other)
{
init();
iterator i = other.begin();
while (i != other.end())
add(*i++);
head = other.head;
tail = other.tail;
}
iterator begin()
{
return iterator(head->next);
}
iterator end()
{
return iterator(tail);
}
Iterator
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; }
int& operator*() { return p->data; }
LinkedListIterator<TNode> operator+(int i)
{
LinkedListIterator<TNode> iter = *this;
while (i-- > 0 && iter.p)
{
++iter;
}
return iter;
}
};
}
Let me know if you need me to post more code. Thanks.

Member functions begin() and end()are defined as non-constant member functions
iterator begin()
{
return iterator(head->next);
}
iterator end()
{
return iterator(tail);
}
However you call them for const object other
LinkedList(const LinkedList& other)
{
init();
iterator i = other.begin(); // <== here
while (i != other.end()) // <== here
add(*i++);
head = other.head;
tail = other.tail;
}
As for error mesdsage
no appropriate default constructor available
then I do not see where the default constructor is used. Nevertheless the error message is clear enough: class LinkedListIterator<Node<T>> has no the default constructor but some where in the code you create an object of this type using the default constructor.

Assuming that 'iterator' is defined as 'LinkedListIterator' it appears that you are attempting to pass the 'head' and 'tail' variables (which appear to be global?) to constructors that do not exist and the compiler is making a last ditched effort to match against a copy constructor (for which there is no match).
I would assume that code should be as follows:
iterator begin()
{
return iterator(head->next.get());
}
iterator end()
{
return iterator(tail.get());
}

Related

Confused on how to implement the end function for doubly linked list

template <typename T>
class LinkedList {
struct node;
class Iterator;
public:
LinkedList() {}
LinkedList(std::initializer_list<T> init_list) {
this->operator=(init_list);
}
template <typename InputIterator>
LinkedList(InputIterator first, InputIterator last) {
for (; first != last; ++first)
this->push_back(*first);
}
LinkedList(const LinkedList& another) {
this->operator=(another);
}
~LinkedList() {
while (this->head) {
node* old_head = this->head;
this->head = old_head->next;
delete old_head;
}
}
Iterator begin() {
return Iterator(this->head);
}
Iterator end() {
return Iterator(this->tail->next);
}
I tried to add an empty node at the tail->next, however I can't get the result that I want. And without the empty node I just get a segmentation fault when I run the code.
class Iterator {
friend class LinkedList;
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = T*;
using reference = T&;
Iterator(node* ptr) : ptr(ptr) {}
Iterator(const Iterator& other) {
this->operator=(other);
}
Iterator& operator=(const Iterator& that) {
this->ptr = that.ptr;
return *this;
}
Iterator& operator++() {
this->ptr = ptr->next;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
this->operator++();
return tmp;
}
Iterator& operator--() {
this->ptr = ptr->prev;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
this->operator--();
return tmp;
}
bool operator!=(Iterator that) const { return !(this->operator==(that)); }
bool operator==(Iterator that) const { return this->ptr == that.ptr; }
T& operator*() const { return ptr->data; }
Iterator* operator->() { return this; }
private:
node* ptr = nullptr;
};
Here is the main function I used to test and when I print the stl_list end() it prints the size of the list. I'm confused what should be returned for this function. I thought it was supposed to be an empty nullptr that points to the location after the tail.
int main() {
std::list<int> stl_list{1, 2, 3, 4, 5};
cs19::LinkedList<int> our_list{1, 2, 3, 4, 5};
std::cout << *stl_list.begin() << '\n';
std::cout << *our_list.begin() << '\n';
std::cout << *our_list.end() << '\n';
std::cout << *stl_list.end() << '\n';
}
Confused on how to implement the end function for doubly linked list
You could create a special node type that is one past the end node which only has a prev pointer.
template <typename T>
class LinkedList {
struct empty_node { // used for end iterator
empty_node* prev = nullptr;
};
struct node : empty_node {
empty_node* next;
T data;
};
Your LinkedList would then have an instance of empty_node whos only purpose is to let prev point back to the last real node. You'd then instantiate the end() iterator with a pointer to this empty_node.
You'd then use empty_node* everywhere until stepping the iterator forward or dereferencing an iterator.
Example with comments to explain:
template <typename T>
class LinkedList {
// node definitions as above
public:
class Iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = T*;
using reference = T&;
Iterator(empty_node* ptr) : ptr(ptr) {}
Iterator(const Iterator& other) : ptr(other.ptr) {}
Iterator& operator=(const Iterator& that) {
ptr = that.ptr;
return *this;
}
Iterator& operator++() {
// If the user steps forward, the iterator can't be at the end
// or the program will have undefined behavior as per the usual
// contract, so a cast is fine:
ptr = static_cast<node*>(ptr)->next;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
++*this;
return tmp;
}
Iterator& operator--() {
ptr = ptr->prev;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
--*this;
return tmp;
}
bool operator==(Iterator that) const { return this->ptr == that.ptr; }
bool operator!=(Iterator that) const {
return !(*this == that);
}
// Dereferencing is not allowed if the iterator is at the end so
// cast is fine:
reference operator*() const { return static_cast<node*>(ptr)->data; }
pointer operator->() { return &static_cast<node*>(ptr)->data; }
private:
empty_node* ptr = nullptr;
};
LinkedList() = default;
template <typename InputIterator>
LinkedList(InputIterator first, InputIterator last) {
for (; first != last; ++first) this->push_back(*first);
}
// Delegate to ctor taking iterators:
LinkedList(std::initializer_list<T> init_list)
: LinkedList(init_list.begin(), init_list.end()) {}
// Copy ctor - delegate to ctor taking iterators too:
LinkedList(const LinkedList& another)
: LinkedList(another.begin(), another.end()) {}
~LinkedList() {
// As long as it's not pointing at end, cast is fine:
for(empty_node* next; head != &beyond_end; head = next) {
next = static_cast<node*>(head)->next;
delete static_cast<node*>(head);
}
}
void push_back(const T& value) {
// Create a new node where `prev` points at the current last real node
// and `next` points at our empty end node:
node* nn = new node{{beyond_end.prev}, &beyond_end, value};
// link it:
if (head != &beyond_end) { // not the first node added
// the previous node must be a real node, so cast is fine:
static_cast<node*>(beyond_end.prev)->next = nn;
} else { // the first node added
head = nn;
}
beyond_end.prev = nn; // link beyond_end to the last real node
}
Iterator begin() { return Iterator(head); }
Iterator end() { return Iterator(&beyond_end); } // use `beyond_end` for end()
private:
empty_node* head = &beyond_end; // start pointing at the empty node
empty_node beyond_end; // note, not a pointer
};
So, instead of a node* tail; you'll have an instance of an empty_node in your LinkedList. It will have the same size as a node* so it doesn't waste space.
Demo
You could also store both the head and tail pointer in an empty_node to remove all casts except when dereferencing/deleteing.
template <typename T>
class LinkedList {
struct empty_node { // used for end iterator
empty_node* prev = nullptr;
empty_node* next = nullptr;
};
struct node : empty_node {
T data;
}
It requires minor changes to the example:
Demo

C2447 in a templated class C++

I'm trying to write a class similar to std::list in C++.
It's my first time dealing with templated classes and I get this weird error:
C2447: '{' missing function header (old-style formal list?)
Here is the code snippet:
template<typename item>
mylist<item>::iterator mylist<item>::erase(iterator pos)
{
iterator cursor(head);
while (cursor->next != (*pos)) ++cursor;
if ((*cursor) == nullptr || (*cursor) == head) return iterator(nullptr);
m_node* tmp = cursor->next->next;
delete cursor->next;
cursor->next = tmp;
--m_size;
return tmp;
}
The class definition:
template<typename item>
class mylist
{
class m_node
{
friend class mylist;
item* node_data;
m_node* next;
public:
m_node()
{
next = nullptr;
node_data = nullptr;
}
m_node(const item& ITEM): m_node()
{
node_data = new item(ITEM);
}
~m_node() { delete node_data; delete next; }
};
m_node* head;
m_node* tail;
unsigned int m_size;
public:
class iterator
{
friend class mylist;
m_node* m_ptr;
public:
iterator()
{
m_ptr = nullptr;
}
iterator(m_node* i_ptr)
{
m_ptr = i_ptr;
}
iterator(const iterator& other)
{
m_ptr = other.m_ptr;
}
~iterator(){}
const iterator& operator=(const iterator& other) const
{
m_ptr = other.m_ptr;
return this;
}
iterator& operator++()
{
++m_ptr;
return *this;
}
item operator->()
{
return *(m_ptr->node_data);
}
item operator*()
{
return *(m_ptr->node_data);
}
bool operator!=(const iterator& other) { return m_ptr != other.m_ptr; }
bool operator ==(const iterator& other) { return m_ptr == other.m_ptr; }
};
mylist()
{
head = tail = new m_node();
m_size = 0;
}
~mylist()
{
delete head;
}
bool isempty() const
{
return head == tail;
}
const iterator& push_back(const item& i_item)
{
tail->next = new m_node(i_item);
tail = tail->next;
++m_size;
return iterator(tail);
}
iterator begin() const
{
return iterator(head);
}
iterator end() const
{
return nullptr;
}
item& back()
{
return *(tail->node_data);
}
unsigned int size() const
{
return m_size;
}
iterator erase(iterator pos);
void remove(item T);
};
The error occurs at the first curly of the function's scope.
I have read some documentations regarding this error and templated classes but could find what seems to be the error.
As mentioned in the comments, you will need a typename preceding the declared return type of the function template. This extra 'hint' for the compiler is required in this case because that return type is dependent on the item type; and, quoting from that linked cppreference page, it is "a compound type constructed from a dependent type".
template<typename item>
typename mylist<item>::iterator mylist<item>::erase(iterator pos)
{
iterator cursor{ head };
while (cursor->next != (*pos)) ++cursor;
if ((*cursor) == nullptr || (*cursor) == head) return iterator(nullptr);
m_node* tmp = cursor->next->next;
delete cursor->next;
cursor->next = tmp;
--m_size;
return tmp;
}
Also note that I have changed the parentheses to curly braces in the iterator cursor{ head }; line; this is now generally accepted as better style, to avoid possible confusion between object initializers and function declarations.

Overloading operator ++ for links in a linked list (c++)

Consider a standard implementation of class Link of LinkedList in c++.
I want to know if its a good idea to overload the operator ++ in this class (I noticed that I repeat the line link = link->next; a lot when dealing with linked lists, so I thought it would be easier if I overload this operator). Here's my implementation:
#ifndef LINK_H
#define LINK_H
#include <iostream>
#include "typeinfo.h"
#include "LinkedList.h"
template <class T> class LinkedList; //|Forward declaration of the generic LinkedList.
template <class T>
class Link
{
public:
//|-------------------- Constructors --------------------
Link(T data): m_data(data), next(NULL){}
//|-------------------- Methods --------------------
T getData(){
return m_data;
}
T& getNext(){
return next;
}
void setNext(Link* newLink){
next = newLink;
}
void setData(T data){
m_data = data;
}
//|-------------------- Operator overload --------------------
bool operator==(Link& other){
if(this->m_data == other.m_data)
return true;
return false;
}
void operator++(){ //Is this okay?
this = this->next;
}
//|-------------------- Friend functions --------------------
friend std::ostream& operator<<(std::ostream& out,const Link<T>& link){
out<<link.m_data;
return out;
}
//|-------------------- Destructor --------------------
virtual ~Link(){}
protected:
public:
//|-------------------- Private fields --------------------
T m_data;
Link<T>* next;
friend class LinkedList<T>;
};
#endif // LINK_H
I guess the way that I tried to do it is not good (it does work as I expected). I tried to use this because I want it to work on pointer that is pointing to a certain link.
So, is it a good idea? if it is, what is the right way to implement it?
Thanks.
Maybe you should refactor your design and the code.
The link, or better said the Node, is normally implemented as an own class. An this class is embedded in the LinkedList class. And that Node class should be completely encapsulated and not shown to the outside world.
The user of the class will just deal with the data value. All the pointer stuff should be hidden.
And to be able to iterate over your class, which is similar to a std::forward_list, you can add ultra simple iterator functionality. Most functions can be implemented using a one liner.
I will show you below an ultra simple implementation example. This may be extended easily according to your needs.
From that you may take over some ideas to improve your design.
With the added iterator functionality, you may use range based for loops and std:: algorithms and all the like.
Please have a look and ask questions, if there should be something unclear.
#include <iostream>
#include <iterator>
#include <initializer_list>
#include <algorithm>
// Very simple implementation of a forward list
template <class T>
class SinglyLinkedList {
// The node
struct Node {
T data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(const T& i, Node* n = nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() const { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<T>& il) { clear(); for (const T& i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const T &i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const T &i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() const { return head == nullptr; }
int size() const { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_front(const T& i) { Node* n = new Node(i); n->next = head; head = n; };
void push_back(const T& i) { Node* n = new Node(i); Node* l = getLast(); if (l) l->next = n; else head = n; }
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, * previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
// Access elements --------------------------------------------------------------------------------
T front() const { return head ? head->data : 0; };
T back() const { Node* n = getLast(); return n ? n->data : 0; }
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
// Define alias names necessary for the iterator functionality
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
// Constructor
iterator() {}
iterator(Node* n) : iter(n) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator +(const difference_type& n) const { iterator temp{ *this }; difference_type k{ n }; while (k--)++temp; return temp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head); }
iterator end() const { return iterator(); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const T& i) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;
delete pos.iter->next;
pos.iter->next = tmp;
result = pos.iter->next;
}
return result;
}
};
// Test/Driver Code
int main() {
// Example for initilizer list
SinglyLinkedList<int> sllbase{ 5,6,7,8,9,10,11,12,13,14,15 };
// Show move constructor
SinglyLinkedList<int> sll(std::move(sllbase));
// Add some values in the front
sll.push_front(4);
sll.push_front(3);
sll.push_front(2);
sll.push_front(1);
// Delete 1st element (Number 1)
sll.pop_front();
// Delete last element
sll.pop_back();
// Use a std::algorithm on our custom linked list. Works because we have an interator
SinglyLinkedList<int>::iterator iter = std::find(sll.begin(), sll.end(), 8);
// Now add an element after 8
iter = sll.insertAfter(iter, 88);
// End delete the 9
iter = sll.eraseAfter(iter);
// Use range based for loop. Works because, we have iterators
for (int i : sll)
std::cout << i << ' ';
}

I need help returning the element at the front of the list *without* using the iterator classes ( assuming the list is not empty)

I'm stuck on this because my program is built for the user of iterators but in this project it also asks us to return the first element on the list not using iterators. I'm a beginner level programmer so my initial thought was returning the head but obviously it can't be that easy because of all the scoping. I get this error:
invalid initialization of reference of type 'int&' from expression of type 'List::Node'
in function Object &raw_front().
Code is below:
#ifndef LIST_H
#define LIST_H
#include <algorithm>
using namespace std;
template<typename Object>
class List {
private:
// The basic doubly linked list node.
// Nested inside of List, can be public
// because the Node is itself private
struct Node {
Object data;
Node *prev;
Node *next;
Node(const Object &d = Object{}, Node *p = nullptr, Node *n = nullptr)
: data{d}, prev{p}, next{n} {}
Node(Object &&d, Node *p = nullptr, Node *n = nullptr)
: data{std::move(d)}, prev{p}, next{n} {}
};
public:
class const_iterator {
public:
// Public constructor for const_iterator.
const_iterator() : current{nullptr} {}
// Return the object stored at the current position.
// For const_iterator, this is an accessor with a
// const reference return type.
const Object &operator*() const { return retrieve(); }
const_iterator &operator++() {
current = current->next;
return *this;
}
const_iterator operator++(int) {
const_iterator old = *this;
++(*this);
return old;
}
const_iterator &operator--() {
current = current->prev;
return *this;
}
const_iterator operator--(int) {
const_iterator old = *this;
--(*this);
return old;
}
bool operator==(const const_iterator &rhs) const { return current == rhs.current; }
bool operator!=(const const_iterator &rhs) const { return !(*this == rhs); }
protected:
Node *current;
// Protected helper in const_iterator that returns the object
// stored at the current position. Can be called by all
// three versions of operator* without any type conversions.
Object &retrieve() const { return current->data; }
// Protected constructor for const_iterator.
// Expects a pointer that represents the current position.
const_iterator(Node *p) : current{p} {}
friend class List<Object>;
};
class iterator : public const_iterator {
public:
// Public constructor for iterator.
// Calls the base-class constructor.
// Must be provided because the private constructor
// is written; otherwise zero-parameter constructor
// would be disabled.
iterator() {}
Object &operator*() { return const_iterator::retrieve(); }
// Return the object stored at the current position.
// For iterator, there is an accessor with a
// const reference return type and a mutator with
// a reference return type. The accessor is shown first.
const Object &operator*() const { return const_iterator::operator*(); }
iterator &operator++() {
this->current = this->current->next;
return *this;
}
iterator operator++(int) {
iterator old = *this;
++(*this);
return old;
}
iterator &operator--() {
this->current = this->current->prev;
return *this;
}
iterator operator--(int) {
iterator old = *this;
--(*this);
return old;
}
protected:
// Protected constructor for iterator.
// Expects the current position.
iterator(Node *p) : const_iterator{p} {}
friend class List<Object>;
};
public:
List() { init(); }
~List() {
// Place your code here.
clear( );
delete head;
delete tail;
}
List(const List &rhs) {
init();
for (auto &x : rhs)
push_back(x);
}
List &operator=(const List &rhs) {
List copy = rhs;
std::swap(*this, copy);
return *this;
}
List(List &&rhs) : theSize{rhs.theSize}, head{rhs.head}, tail{rhs.tail} {
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
List &operator=(List &&rhs) {
std::swap(theSize, rhs.theSize);
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
return *this;
}
// Return iterator representing beginning of list.
// Mutator version is first, then accessor version.
iterator begin() { return iterator(head->next); }
const_iterator begin() const { return const_iterator(head->next); }
// Return iterator representing endmarker of list.
// Mutator version is first, then accessor version.
iterator end() { return iterator(tail); }
const_iterator end() const { return const_iterator(tail); }
// Return number of elements currently in the list.
int size() const { return theSize; }
// Return true if the list is empty, false otherwise.
bool empty() const { return size() == 0; }
void clear() {
while (!empty())
pop_front();
}
// front, back, push_front, push_back, pop_front, and pop_back
// are the basic double-ended queue operations.
Object &front() { return *begin(); }
Object &raw_front() {
// Return the element at the front of the list *without* using the iterator classes
// (You may assume the list is not empty)
// (Yes, this is bad code. I just needed something that will allow the stub to compile.)
return head ;
}
const Object &front() const { return *begin(); }
Object &back() { return *--end(); }
Object &raw_back() {
// Return the element at the end of the list *without* using the iterator classes
// (You may assume the list is not empty)
// Place your code here.
// (Yes, this is bad code. I just needed something that will allow the stub to compile.)
return tail;
}
const Object &back() const { return *--end(); }
void push_front(const Object &x) { insert(begin(), x); }
void push_back(const Object &x) { insert(end(), x); }
void raw_push_front(const Object &x) {
// insert x at the head of the list *without* using the iterator classes
// Place your code here.
Node *p = new Node(x, nullptr, head);
if(tail == nullptr)
tail = p;
head = p;
++theSize;
}
void raw_push_back(const Object &x) {
// insert x at the tail of the list *without* using the iterator classes
// Place your code here.
Node *p = new Node(x, tail, nullptr);
if(head == nullptr)
head = p;
tail = p;
++theSize;
}
void raw_insert_in_order(const Object &x) {
// insert x into the sorted list *without* using the iterator classes.
// You may assume the list is either empty or correctly sorted.
// Place your code here.
}
void push_front(Object &&x) { insert(begin(), std::move(x)); }
void push_back(Object &&x) { insert(end(), std::move(x)); }
void pop_front() { erase(begin()); }
void pop_back() { erase(--end()); }
// Insert x before itr.
iterator insert(iterator itr, const Object &x) {
Node *p = itr.current;
++theSize;
return iterator(p->prev = p->prev->next = new Node{x, p->prev, p});
}
// Insert x before itr.
iterator insert(iterator itr, Object &&x) {
Node *p = itr.current;
++theSize;
return iterator(p->prev = p->prev->next = new Node{std::move(x), p->prev, p});
}
// Erase item at itr.
iterator erase(iterator itr) {
Node *p = itr.current;
iterator retVal(p->next);
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
--theSize;
return retVal;
}
iterator erase(iterator from, iterator to) {
for (iterator itr = from; itr != to;)
itr = erase(itr);
return to;
}
void splice(iterator position, List<Object> &lst ) {
// Removes all the items from lst, add them prior to position in *this.
// You may assume lst and *this are different lists.
// **Your routine must run in constant time.**
Node *p = position.current;
theSize += lst.size();
p->prev->next = lst.head->next;
lst.head->next->prev = p->prev;
lst.tail->prev->next = p;
p->prev = lst.tail->prev;
lst.init();
}
private:
int theSize;
Node *head;
Node *tail;
void init() {
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
};
#endif

no match for operator!=

I am trying to create linked list class and define the iterators, I have all of them except the last one. I dont get how to fix, i get this error when i compile my code:
no match for ‘operator!=’ in ‘recList.SortedList::begin with T = Record != recList.SortedList::end with T = Record’
a1q1main.cpp:114:37: note: candidates are:
sortedlist.h:112:11: note: SortedList::iterator SortedList::iterator::operator!=(bool) [with T = Record, SortedList::iterator = SortedList::iterator]
sortedlist.h:112:11: note: no known conversion for argument 1 from ‘SortedList::iterator’ to ‘bool’
It keeps on displaying this error no matter what i do
I have declared operator == and everything is fine but the != complains
Here is the code :
class SortedList {
struct Node {
T data_;
Node* next_;
Node* prev_;
Node(const T& data = T{}, Node* next = nullptr, Node* prev = nullptr) {
data_ = data;
next_ = next;
prev_ = prev;
}
};
Node* head_;
Node* tail_;
public:
class const_iterator {
protected:
Node* curr_;
public:
const_iterator(Node* p) {
curr_ = p;
}
.........
const_iterator operator--(int) {
const_iterator tmp = *this;
curr_ = curr_->prev_;
return tmp;
}
const T& operator*() const {
return curr_->data_;
}
const_iterator operator==(bool){
return false;
}
const_iterator operator!=(bool){
return true;
}
return;`
I need to fulfill the criteria below:
operator !=
returns true if two iterators point at different nodes, false otherwise
O(1)
I did not complete the logic of the operator, i just need to declare it properly so i dont get the error
The signature of your operator overloads are incorrect. You have them accepting a bool and returning an iterator. It should be the other way around.
Consider the operation you are performing
if(it1 == it2){
// do stuff
}
You even return a bool in your functions despite the signature requiring a iterator as return value.
Instead implement the operator overloads in the required signature
bool operator==(sorted_list_iterator it){
return (curr_->data_ == it.curr_->data_);
}
bool operator!=(sorted_list_iterator it){
return !(*this == it);
}
Note you can use your operator== overload in your operator!= to avoid repeating the equality logic in two functions. You may also be required to allow for a null curr_ in those functions.