Question
#ifndef LIST_H #define LIST_H #include using namespace std; template class List { private: // The basic doubly linked list node. // Nested inside of List,
#ifndef LIST_H #define LIST_H
#include
template
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: // 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
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
private: int theSize; Node *head; Node *tail; { return const_iterator::init(); for( auto & x : rhs ) push_back( x ); }
void init( ) { theSize = 0; head = new Node; tail = new Node; head->next = tail; tail->prev = head; } };
#endif
Try to complete the code in List.h to make main.cpp work. It's simply trying to generate a list, and show the list.
Here is the instruction:
1. Insert the following code to define Node in List class:
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 } { }
2. Define the Nested const_iterator class for List class:
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;
3. Define the Nested iterator class for List class
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;
4. Define init() function:
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
5. Add code to constructor List() to generate an empty list:
init();
6. Add code to constructor List( const List & rhs ) to initialize a list with values.
init( );
for( auto & x : rhs )
push_back( x );
7. Add code to constructor List( List & rhs ) to initialize an empty list.
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
8. Add code to destructor ~List():
clear( );
delete head;
delete tail;
9. Add code for operator =
List & operator= ( const List & rhs )
List copy = rhs;
std::swap( *this, copy );
return *this;
List & operator= ( List && rhs )
std::swap( theSize, rhs.theSize );
std::swap( head, rhs.head );
std::swap( tail, rhs.tail );
return *this;
10. Use the following code to complete insert functions:
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 } );
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 } );
11. Add code to erase a node:
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;
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started