```/**
* @file
* @brief Implementation of [Reversing
* @details
* The linked list is a data structure used for holding a sequence of
* values, which can be added, displayed, reversed, or removed.
* ### Algorithm
* Values can be added by iterating to the end of a list (by following
* the pointers) starting from the first link. Whichever link points to null
* is considered the last link and is pointed to the new value.
*
* Linked List can be reversed by using 3 pointers: current, previous, and
* next_node; we keep iterating until the last node. Meanwhile, before changing
* to the next of current, we store it in the next_node pointer, now we store
* the prev pointer in the current of next, this is where the actual reversal
* happens. And then we move the prev and current pointers one step forward.
* Then the head node is made to point to the last node (prev pointer) after
* completion of an iteration.

* [A graphic explanation and view of what's happening behind the
*/

#include <cassert>   /// for assert
#include <iostream>  /// for I/O operations
#include <new>       /// for managing  dynamic storage

/**
* @namespace data_structures
* @brief Data Structures algorithms
*/
namespace data_structures {
/**
* @brief Functions for singly linked list algorithm
*/
/**
* A Node class containing a value and pointer to another link
*/
class Node {
public:
int32_t val;  /// value of the current link
Node* next;   /// pointer to the next value on the list
};

/**
*  @brief creates a deep copy of a list starting at the input node
*  @param[in] node pointer to the first node/head of the list to be copied
*  @return pointer to the first node/head of the copied list or nullptr
*/
Node* copy_all_nodes(const Node* const node) {
if (node) {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
Node* res = new Node();
res->val = node->val;
res->next = copy_all_nodes(node->next);
return res;
}
return nullptr;
}

/**
* A list class containing a sequence of links
*/
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class list {
private:
void delete_all_nodes();
void copy_all_nodes_from_list(const list& other);

public:
bool isEmpty() const;
void insert(int32_t new_elem);
void reverseList();
void display() const;
int32_t top() const;
int32_t last() const;
int32_t traverse(int32_t index) const;
~list();
list() = default;
list(const list& other);
list& operator=(const list& other);
};

/**
* @brief Utility function that checks if the list is empty
* @returns true if the list is empty
* @returns false if the list is not empty
*/
bool list::isEmpty() const { return head == nullptr; }

/**
* @brief Utility function that adds a new element at the end of the list
* @param new_elem element be added at the end of the list
*/
void list::insert(int32_t n) {
try {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
Node* new_node = new Node();
Node* temp = nullptr;
new_node->val = n;
new_node->next = nullptr;
if (isEmpty()) {
} else {
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new_node;
}
std::cerr << "bad_alloc detected: " << exception.what() << "\n";
}
}

/**
* @brief Utility function for reversing a list
* @brief Using the current, previous, and next pointer.
* @returns void
*/
void list::reverseList() {
Node* prev = nullptr;
Node* next_node = nullptr;
while (curr != nullptr) {
next_node = curr->next;
curr->next = prev;
prev = curr;
curr = next_node;
}
}

/**
* @brief Utility function to find the top element of the list
* @returns the top element of the list
*/
int32_t list::top() const {
if (!isEmpty()) {
} else {
throw std::logic_error("List is empty");
}
}
/**
*  @brief Utility function to find the last element of the list
*  @returns the last element of the list
*/
int32_t list::last() const {
if (!isEmpty()) {
while (t->next != nullptr) {
t = t->next;
}
return t->val;
} else {
throw std::logic_error("List is empty");
}
}
/**
*  @brief Utility function to find the i th element of the list
*  @returns the i th element of the list
*/
int32_t list::traverse(int32_t index) const {

int count = 0;
while (current != nullptr) {
if (count == index) {
return (current->val);
}
count++;
current = current->next;
}

/* if we get to this line,the caller was asking for a non-existent element
so we assert fail */
exit(1);
}

/**
*  @brief calls delete operator on every node in the represented list
*/
void list::delete_all_nodes() {
}
}

list::~list() { delete_all_nodes(); }

void list::copy_all_nodes_from_list(const list& other) {
assert(isEmpty());
}

/**
*  @brief copy constructor creating a deep copy of every node of the input
*/
list::list(const list& other) { copy_all_nodes_from_list(other); }

/**
*  @brief assignment operator creating a deep copy of every node of the input
*/
list& list::operator=(const list& other) {
if (this == &other) {
return *this;
}
delete_all_nodes();

copy_all_nodes_from_list(other);
return *this;
}

}  // namespace data_structures

/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st test
L.insert(11);
L.insert(12);
L.insert(15);
L.insert(10);
L.insert(-12);
L.insert(-20);
L.insert(18);
assert(L.top() == 11);
assert(L.last() == 18);
L.reverseList();
// Reversal Testing
assert(L.top() == 18);
assert(L.traverse(1) == -20);
assert(L.traverse(2) == -12);
assert(L.traverse(3) == 10);
assert(L.traverse(4) == 15);
assert(L.traverse(5) == 12);
assert(L.last() == 11);
std::cout << "All tests have successfully passed!" << std::endl;
}

void test_copy_constructor() {
L.insert(10);
L.insert(20);
L.insert(30);
otherList.insert(40);

L.insert(400);

assert(L.top() == 10);
assert(otherList.top() == 10);
assert(L.traverse(1) == 20);
assert(otherList.traverse(1) == 20);

assert(L.traverse(2) == 30);
assert(otherList.traverse(2) == 30);

assert(L.last() == 400);
assert(otherList.last() == 40);
}

void test_assignment_operator() {
L.insert(10);
L.insert(20);
L.insert(30);
otherList = L;

otherList.insert(40);
L.insert(400);

assert(L.top() == 10);
assert(otherList.top() == 10);
assert(L.traverse(1) == 20);
assert(otherList.traverse(1) == 20);

assert(L.traverse(2) == 30);
assert(otherList.traverse(2) == 30);

assert(L.last() == 400);
assert(otherList.last() == 40);
}

/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test();  // run self-test implementations
test_copy_constructor();
test_assignment_operator();
return 0;
}
```