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 using namespace std;

template class List { private: // The basic doubly linked list node. // Nested inside of List, can be public // because the Node is itself private struct Node { //Add code to define Node. };

public: class const_iterator { //Add code to define const_iterator class };

class iterator : public const_iterator { //Add code to define iterator class };

public: List( ) { //Add code for the constructor to initialize a empty list. }

~List( ) { //Add code to clean up the List. }

List( const List & rhs ) { //Add code for the constructor to initialize a list with values. }

List( List && rhs ) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail } { //Add code. }

List & operator= ( const List & rhs ) { //Add code } List & operator= ( List && rhs ) { //Add code } // 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( ); }

const Object & front( ) const { return *begin( ); }

Object & back( ) { return *--end( ); }

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 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 ) { //add code. }

// Insert x before itr. iterator insert( iterator itr, Object && x ) { //Add code. } // Erase item at itr. iterator erase( iterator itr ) { //Add code. }

iterator erase( iterator from, iterator to ) { for( iterator itr = from; itr != to; ) itr = erase( itr );

return to; }

private: int theSize; Node *head; Node *tail;

void init( ) { //Add code here to define the function to initialize list. } };

#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

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!