I wrote this implementation of a singly linked list but I don't find my code enough simple and compact. Could you help me to simplify it?
Includes
#include <exception>
#include <iostream>
Structure of data elements
template<typename T>
struct Link {
T val;
Link<T>* next;
};
Class of singly linked list
template<typename T>
class SLinkedList {
public:
//Default constructor
SLinkedList(): first_(NULL), size_(0) {}
//Copy constructor
SLinkedList(const SLinkedList<T>& other) {
if(other.first_) {
first_ = new Link<T>();
size_ = other.size_;
Link<T>* index1 = first_;
Link<T>* index2 = other.first_;
index1->val = index2->val;
while(index2->next) {
index1->next = new Link<T>();
index1 = index1->next;
index2 = index2->next;
index1->val = index2->val;
}
}
else first_ = other.first_;
}
//Destructor
~SLinkedList() {
clear();
}
//Index operator
T& operator[](int i) {
if(first_) {
if(i < 0 || i+1 > size_)
throw std::out_of_range("index out of range!!!");
if(i == 0) return first_->val;
Link<T>* index = first_;
for(int it=0; it<i; it++) index = index->next;
return index->val;
}
else throw std::out_of_range("empty list!!!");
}
//Access first element
T& front() {
return first_->val;
}
//Access last element
T& back() {
return end()->val;
}
//Add an element at the begining
void push_front(const T& value) {
Link<T>* temp = new Link<T>();
temp->val = value;
temp->next = first_;
first_ = temp;
size_++;
}
//Add an element at the end
void push_back(const T& value) {
Link<T>* temp = new Link<T>();
temp->val = value;
temp->next = NULL;
size_++;
if(!first_) first_ = temp;
else {
Link<T>* last = end();
last->next = temp;
}
}
//Remove elements with specific value
void remove(const T& value) {
if(first_) {
Link<T>* index = first_;
Link<T>* temp = NULL;
while(index && index->val == value) {
index = index->next;
delete first_;
first_ = index;
size_--;
}
while(index->next) {
if(index->next->val == value) {
if(index->next->next) {
temp = index->next->next;
delete index->next;
index->next = temp;
}
else {
delete index->next;
index->next = NULL;
}
size_--;
}
else index = index->next;
}
}
}
//Delete first element
void pop_front() {
if(first_) {
Link<T>* first = first_->next;
delete first_;
first_ = first;
size_--;
}
}
//Delete last element
void pop_back() {
if(first_) {
Link<T>* index1 = first_;
Link<T>* index2 = NULL;
while(index1->next) {
index2 = index1;
index1 = index1->next;
}
delete index1;
index2->next = NULL;
size_--;
}
}
//Clear content
void clear() {
if(first_) {
Link<T>* index = first_;
Link<T>* temp = NULL;
while(index) {
temp = index;
index = index->next;
delete temp;
}
size_ = 0;
}
}
//Return size
int size() const {
return size_;
}
//Invert content
void reverse() {
if(first_) {
Link<T>* first = new Link<T>();
Link<T>* temp = NULL;
first->val = first_->val;
Link<T>* index = first_;
while(index->next) {
index = index->next;
temp = first;
first = new Link<T>();
first->val = index->val;
first->next = temp;
}
clear();
first_ = first;
}
}
//Display elements on output standard
void print() const {
Link<T>* index = first_;
std::cout << index->val;
while(index->next) {
index = index->next;
std::cout << "; " << index->val ;
}
std::cout << std::endl;
}
private:
//Access last pointer of data element
Link<T>* end() const {
if(!first_) return first_;
Link<T>* index = first_;
while(index->next)
index = index->next;
return index;
}
//First pointer of data element
Link<T>* first_;
//Size of list
int size_;
};