this program gets and stores information about students , you can add , remove and also add and remove course for every student , also prints the information


but how can i add the ability to calculate GPA for every student ? like after asking the course name , can someone change it so that it would ask the grade of the course , then after that changes the GPA of the student and stores it , also prints it


also if you can correct any part of the code and make it simpler and easier to understand it would be great


Code:
#include <iostream>
#include <iomanip>

template<typename T>
class linkedlist {
private:
    struct node {
        node *prev;
        node *next;
        T data;

        node() {
        }

        node(node *prev, node *next, const T &data) :
                prev(prev), next(next), data(data) {
        }
    };

    node first;
    node last;

public:
    linkedlist() :
            first(nullptr, &last, T()),
            last(&first, &last, T()) {
    }

    linkedlist(const T & nil) :
            first(nullptr, &last, nil),
            last(&first, &last, nil) {
    }

    linkedlist(const linkedlist<T> &other) :
            first(nullptr, &last, T()),
            last(&first, &last, T()) {
        (*this) = other;
    }

    class iterator {
        friend class linkedlist;

    private:
        node *current_node;

        iterator(node *current_node) : current_node(current_node) {
        }

    public:
        iterator(const iterator &other_iterator) : current_node(other_iterator.current_node) {
        }

        T &operator*() {
            return current_node->data;
        }

        const T &operator*() const {
            return current_node->data;
        }

        iterator &operator++() {
            current_node = current_node->next;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = iterator(*this);
            ++(*this);
            return tmp;
        }

        bool operator!=(const iterator &other) const {
            return current_node != other.current_node;
        }

        bool operator==(const iterator &other) const {
            return current_node == other.current_node;
        }
    };

    class const_iterator {
        friend class linkedlist;

    private:
        const node *current_node;

        const_iterator(const node *current_node) : current_node(current_node) {
        }

    public:
        const_iterator(const const_iterator &other_iterator) : current_node(other_iterator.current_node) {
        }

        const T &operator*() const {
            return current_node->data;
        }

        const_iterator &operator++() {
            current_node = current_node->next;
            return *this;
        }

        const_iterator operator++(int) {
            const_iterator tmp = const_iterator(*this);
            ++(*this);
            return tmp;
        }

        bool operator!=(const const_iterator &other) const {
            return current_node != other.current_node;
        }

        bool operator==(const const_iterator &other) const {
            return current_node == other.current_node;
        }
    };

    T &append(const T &data) {
        node *new_node = new node(last.prev, &last, data);
        new_node->prev->next = new_node;
        new_node->next->prev = new_node;
        return new_node->data;
    }

    iterator &erase(iterator &&iterator) {
        if (iterator.current_node == &first || iterator.current_node == &last)
            return iterator;
        node *to_remove = iterator.current_node;
        ++iterator;
        to_remove->prev->next = to_remove->next;
        to_remove->next->prev = to_remove->prev;
        delete to_remove;
        return iterator;
    }

    iterator erase(iterator &iterator) {
        if (iterator.current_node == &first || iterator.current_node == &last)
            return iterator;
        node *to_remove = iterator.current_node;
        ++iterator;
        to_remove->prev->next = to_remove->next;
        to_remove->next->prev = to_remove->prev;
        delete to_remove;
        return iterator;
    }

    iterator begin() {
        return iterator(first.next);
    }

    iterator end() {
        return iterator(&last);
    }

    const_iterator cbegin() const {
        return const_iterator(first.next);
    }

    const_iterator cend() const {
        return const_iterator(&last);
    }

    iterator find(const T &data) {
        for (iterator it = begin(); it != end(); ++it) {
            T &current_item = *it;
            if (current_item == data) {
                return it;
            }
        }
        return end();
    }

    bool operator==(const linkedlist<T> &other) {
        const_iterator other_it = other.cbegin();
        const_iterator self_it = cbegin();

        while (other_it != other.cend() || other_it != other.cend()) {
            if (*self_it != *other_it) return false;
            ++self_it;
            ++other_it;
        }

        return other_it == other.cend() && other_it == other.cend();
    }

    linkedlist<T>&operator=(const linkedlist<T> &other) {
        this->first.data = other.first.data;
        this->last.data = other.last.data;
        for (linkedlist<T>::const_iterator it = other.cbegin(); it != other.cend(); it++) {
            append(*it);
        }
        return *this;
    }

    ~linkedlist() {
        while (begin() != end()) {
            erase(begin());
        }
    }
};

struct student {
    std::string name;
    linkedlist<std::string> courses;

    student() : name(""), courses("") {
    }

    student(const student &student) : name(student.name), courses(student.courses) {
    }

    student(const std::string &name) : name(name), courses("") {
    }

    bool operator==(const student &other) {
        return name == other.name && courses == other.courses;
    }
};

linkedlist<student> database;

void add_course(student &std) {
    std::cout << "Main > Student \"" << std.name << "\"" << " > Add course" << std::endl;
    while (true) {
        std::cout << "Enter course to add (or \"back\" to go back): ";
        std::string query;
        std::cin >> query;

        if (query == "back")
            return;

        linkedlist<std::string>::iterator found = std.courses.find(query);
        if (found == std.courses.end()) {
            std.courses.append(query);
            std::cout << "Course " << "\"" << query << "\"" << " successfully created" << std::endl;
            return;
        }
        else {
            std::cout << "Course " << "\"" << query << "\"" << " already exists" << std::endl;
        }
    }
}

void remove_course(student &std) {
    std::cout << "Main > Student \"" << std.name << "\"" << std::endl;
    while (true) {
        std::cout << "Enter course to remove (or \"back\" to go back): ";
        std::string query;
        std::cin >> query;

        if (query == "back")
            return;

        linkedlist<std::string>::iterator found = std.courses.find(query);
        if (found == std.courses.end()) {
            std::cout << "Course " << "\"" << query << "\"" << " Not found" << std::endl;
        }
        else {
            std.courses.erase(found);
            std::cout << "Course " << "\"" << query << "\"" << " successfully removed" << std::endl;
            return;
        }
    }

}

void remove_student(student &std) {
    linkedlist<student>::iterator iterator = database.find(std);
    database.erase(iterator);
    std::cout << "Student \"" << std.name << "\" removed successfully" << std::endl;
}

void show_courses(student &std) {
    std::cout << "Main > Student \"" << std.name << "\" > Course List" << std::endl;
    int i = 0;
    for (linkedlist<std::string>::const_iterator it = std.courses.cbegin(); it != std.courses.cend(); it++) {
        std::string course_name = *it;
        std::cout << std::left << std::setw(5) << ++i << course_name << std::endl;
    }
}

void student_menu(student &std) {
    while (true) {
        std::cout << "Main > Student \"" << std.name << "\"" << std::endl
        << "\t1) Add course" << std::endl
        << "\t2) Remove course" << std::endl
        << "\t3) Show courses" << std::endl
        << "\t4) Remove student" << std::endl
        << "\t5) Go back" << std::endl
        << "Enter your option: ";

        int option = 0;
        std::cin >> option;
        switch (option) {
            case 1:
                std::cout << std::endl;
                add_course(std);
                std::cout << std::endl;
                break;
            case 2:
                std::cout << std::endl;
                remove_course(std);
                std::cout << std::endl;
                break;
            case 3:
                std::cout << std::endl;
                show_courses(std);
                std::cout << std::endl;
                break;
            case 4:
                std::cout << std::endl;
                remove_student(std);
                return;
            case 5:
                return;
            default:
                std::cout << "Invalid option: " << option << std::endl;
        }
    }
}

void add_student() {
    std::cout << "Main > Create new student " << std::endl;
    std::string student_name;

    while (true) {
        std::cout << "Enter student name (or \"back\" to go back): ";
        std::cin >> student_name;

        if (student_name == "back")
            return;

        if (student_name.empty()) {
            std::cout << "Error: Student name can not be empty!" << std::endl;
            continue;
        }
        for (linkedlist<student>::const_iterator it = database.cbegin(); it != database.cend(); it++) {
            const student &older_student = *it;
            if (older_student.name == student_name) {
                std::cout << "Error: Student already exists" << std::endl;
                continue;
            }
        }
        std::cout << "Student \"" << student_name << "\" created successfully" << std::endl;
        break;
    }

    student student(student_name);

    std::cout << std::endl;
    student_menu(database.append(student));
}

void list_students() {
    std::cout << "Main > List students" << std::endl;
    int i = 0;
    for (linkedlist<student>::const_iterator it = database.cbegin(); it != database.cend(); it++) {
        const student &std = *it;
        std::cout << std::setw(5) << std::left << ++i << std.name << std::endl;
    }
}


void find_student() {
    std::cout << "Main > Find student" << std::endl;
    while (true) {
        std::cout << "Enter student name (or enter \"back\" to go back): ";
        std::string query;
        std::cin >> query;
        if (query == "back") return;
        for (linkedlist<student>::iterator it = database.begin(); it != database.end(); it++) {
            student &std = *it;
            if (std.name == query) {
                student_menu(std);
                break;
            }
        }
        std::cout << "Error: Student not found!" << std::endl;
    }
}

void main_menu() {
    while (true) {
        std::cout << "Main" << std::endl
        << "\t1) Add student" << std::endl
        << "\t2) List students" << std::endl
        << "\t3) Find a student" << std::endl
        << "\t4) Exit" << std::endl
        << "Enter your option: ";


        int option = 0;
        std::cin >> option;

        std::cout << std::endl;

        switch (option) {
            case 1:
                add_student();
                break;
            case 2:
                list_students();
                break;
            case 3:
                find_student();
                break;
            case 4:
                std::cout << "Goodbye";
                return;
            default:
                std::cout << "Invalid option: " << option << std::endl;
        }

        std::cout << std::endl;
    }
}

int main() {
    main_menu();

    return EXIT_SUCCESS;
}