#include <cassert>
#include <iostream>
#include <memory>
using namespace std;
class List {
public:
List() = default;
// ~List() = default; also works.
~List() {
cout << "Enter List destructor\n";
// Release |front_| explicitly to see how the Node is released.
front_ = nullptr;
cout << "List destructor done\n";
}
int front() const {
assert(front_);
return front_->element;
}
bool empty() const {
return size_ == 0;
}
size_t size() const {
return size_;
}
void push_front(int element) {
unique_ptr<Node> new_front = make_unique<Node>(element, move(front_));
front_ = move(new_front);
size_++;
}
void pop_front() {
front_ = move(front_->next_node);
size_--;
}
void insert_at(int index, int element) {
assert(index <= size_);
// |front_| will be updated to the new node. Handle it separately.
if (index == 0) {
push_front(element);
return;
}
// Here we don't need the ownership of the node when finding the insert
// point. Just use the raw pointer.
Node* front_node = front_.get();
for (size_t i = 0; i < index - 1; i++) {
front_node = front_node->next_node.get();
}
unique_ptr<Node> new_node = make_unique<Node>(
element, move(front_node->next_node));
front_node->next_node = move(new_node);
size_++;
}
void print() const {
// We don't need the ownership of the node when triversing the list.
// Just use the raw pointer.
Node* p = front_.get();
while (p != nullptr) {
cout << p->element << " -> ";
p = p->next_node.get();
}
cout << "NULL" << endl << "size = " << size_ << endl;
}
private:
// The list client doesn't need to know the detail about Node, so put it in
// private. Node only has public data members. Just use struct.
struct Node {
Node(int e, unique_ptr<Node> n)
: element(e), next_node(move(n)) {}
~Node() {
cout << "Node " << element << " is released.\n";
}
int element;
unique_ptr<Node> next_node;
};
unique_ptr<Node> front_;
size_t size_ = 0;
};
int main() {
List myList;
myList.push_front(23);
myList.push_front(24);
myList.push_front(25);
myList.push_front(27);
myList.push_front(2);
myList.push_front(32);
myList.print();
myList.insert_at(4, 89);
myList.print();
myList.pop_front();
myList.print();
cout << "Exit main(). After that List destructor will be triggered.\n";
return 0;
}