Search code examples
operator-overloading

Custom C++ classes, cannot overload the correct operator


heres the code

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <list>

using namespace std;

class Author {

public:

    Author() = default;

    ~Author() {
        delete[] _IDs;
        _IDs = nullptr;
    }

    Author(const char* Name, const char* BirthDate, const int ID)
        : _name(Name)
        , _birthdate(BirthDate)
        , _ID(ID)
    {
        
        for (int i = 0; i < _size; i++) {
            if (ID == _IDs[i]) {
                delete[] _IDs;
                _IDs = nullptr;
                throw new std::invalid_argument("ID Must be UNIQUE;");
            }
        }
            
        check_alloc_ID_size();
        _IDs[_size++] = ID;
    }


    Author(const Author& other)
        : _name(other._name)
        , _birthdate(other._birthdate)
        , _ID(other._ID)
    {}

public:

    const char* GetBD() const { return _birthdate; }

    const char* GetName() const { return _name; }

    const int GetID() const { return _ID; }


private:
    const char* _name;
    const char* _birthdate;
    const int _ID;

    static int* _IDs;
    static int _size;
    static int _alloc_size;

private:

    void check_alloc_ID_size() {
        if (_size == _alloc_size) {
            int* temp = _IDs;
            _alloc_size *= 2;
            _IDs = new int[_alloc_size];

            for (int i = 0; i < _size; i++) {
                _IDs[i] = temp[i];
            }
            delete[] temp;
        }
    }
};

int* Author::_IDs = new int[1];
int Author::_size = 0;
int Author::_alloc_size = 1;

class Book {

public:

    Book(const char* title, const char* isbn, const int year, const Author& author)
        : _title(title)
        , _isbn(isbn)
        , _year(year)
        , _author(author)
    {}

    const char* GetTitle() const { return _title; }
    const char* GetIsbn() const { return _isbn; }
    const int GetYear() const { return _year; }
    const Author& GetAuthor() const { return _author; }

    void PrintBookInfo() {

        printf("%s\n%s\n%d\n", GetTitle(), GetIsbn(), GetYear());
    }

    bool operator==(const Book& other) const {
        return _isbn == other._isbn;
    }


private:
    const char* _title;
    const char* _isbn;
    const int _year;
    const Author& _author;

};

class Patron {
public:

    Patron() {}

    bool operator==(const Patron& other) const {
        return _libID == other._libID;
    }
    
private:

    const char*     _name;
    const char*     _libID;
    vector<Book>    _checked;
};


class Library {

public:

    Library()
    {}

    void AddBook(const Book& book) {
        _books.push_back(make_pair(book, 1));
    }

    
    void RemoveBook(const Book& book) {
        for (auto it = _books.begin(); it != _books.end(); ++it) {
            if ((*it).first == static_cast<const Book&>(book)) {
                _books.erase(it);
                break;
            }
        }
    }
    

    void AddPatron(const Patron& patron) {
        _patrons.push_back(patron);
    }

    
    void RemovePatron(const Patron& patron) {
        for (auto it = _patrons.begin(); it != _patrons.end(); ++it) {
            if (*it == patron) {
                _patrons.erase(it);
                break;
            }
        }
    }
    


private:
    
    vector<pair<Book, int>> _books;
    vector<Patron>          _patrons;

    vector<Book>            _checked_out_books;
    vector<Book>            _available_books;
};


Now the error is in the RemoveBook() function, and it pertains to an operator not being overloaded. I triet multiple solutions and even chat GPT couldn't figure it out. IF you aren't SURE it works, I probably already tried it. Any thanks greatly welcome!

It says to add more details. At first I was adding operator overloads in the Book class, then realised that the _books if in the library class. Im comparing Pair<> here so I'm not sure how the operator should go. Like I said I spent 3 hours with chatGPT giving me the wrong answers.

The iterator continuation doesn't matter like GPT suggests, you can just break out of the code, even though I tried that too.


Solution

  • Here is the working code

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <vector>
    #include <list>
    
    using namespace std;
    
    class Author {
    
    public:
    
        Author() = default;
    
        ~Author() {
            delete[] _IDs;
            _IDs = nullptr;
        }
    
        Author(const char* Name, const char* BirthDate, const int ID)
            : _name(Name)
            , _birthdate(BirthDate)
            , _ID(ID)
        {
            
            for (int i = 0; i < _size; i++) {
                if (ID == _IDs[i]) {
                    delete[] _IDs;
                    _IDs = nullptr;
                    throw new std::invalid_argument("ID Must be UNIQUE;");
                }
            }
                
            check_alloc_ID_size();
            _IDs[_size++] = ID;
        }
    
    
        Author(const Author& other)
            : _name(other._name)
            , _birthdate(other._birthdate)
            , _ID(other._ID)
        {}
    
    public:
    
        const char* GetBD() const { return _birthdate; }
    
        const char* GetName() const { return _name; }
    
        const int GetID() const { return _ID; }
    
    
    private:
        const char* _name;
        const char* _birthdate;
        int _ID;
    
        static int* _IDs;
        static int _size;
        static int _alloc_size;
    
    private:
    
        void check_alloc_ID_size() {
            if (_size == _alloc_size) {
                int* temp = _IDs;
                _alloc_size *= 2;
                _IDs = new int[_alloc_size];
    
                for (int i = 0; i < _size; i++) {
                    _IDs[i] = temp[i];
                }
                delete[] temp;
            }
        }
    };
    
    int* Author::_IDs = new int[1];
    int Author::_size = 0;
    int Author::_alloc_size = 1;
    
    class Book {
    
    public:
        Book(const char* title, const char* isbn, const int year, const Author& author)
            : _title(title)
            , _isbn(isbn)
            , _year(year)
            , _author(author)
        {}
    
        const char* GetTitle() const { return _title; }
        const char* GetIsbn() const { return _isbn; }
        const int GetYear() const { return _year; }
        const Author& GetAuthor() const { return _author; }
    
        void PrintBookInfo() {
    
            printf("%s\n%s\n%d\n", GetTitle(), GetIsbn(), GetYear());
        }
    
        bool operator==(const Book& other) const {
            return _isbn == other._isbn;
        }
    
    
    private:
        const char* _title;
        const char* _isbn;
        int _year = 9;
        Author _author;
    
    };
    
    class Patron {
    public:
    
        Patron() {}
    
        bool operator==(const Patron& other) const {
            return _libID == other._libID;
        }
        
    private:
    
        const char*     _name;
        const char*     _libID;
        vector<Book>    _checked;
    };
    
    
    class Library {
    
    public:
    
        Library()
        {}
    
        void AddBook(const Book& book) {
            _books.push_back(make_pair(book, 1));
        }
    
        
        void RemoveBook(const Book& book) {
            for (auto it = _books.begin(); it != _books.end(); ++it) {
                if ((*it).first == static_cast<const Book&>(book)) {
                    _books.erase(it);
                    break;
                }
            }
        }
        
    
        void AddPatron(const Patron& patron) {
            _patrons.push_back(patron);
        }
    
        
        void RemovePatron(const Patron& patron) {
            for (auto it = _patrons.begin(); it != _patrons.end(); ++it) {
                if (*it == patron) {
                    _patrons.erase(it);
                    break;
                }
            }
        }
        
    
    
    private:
        
        vector<pair<Book, int>> _books;
        vector<Patron>          _patrons;
    
        vector<Book>            _checked_out_books;
        vector<Book>            _available_books;
    };
    

    The problem is that _books.erase() performs a std::move operation however Book can not provide a default move constructor because it has a const reference member const Author& _author which needs to be initialized on construction. Consequently you'd have to provide an Author& in the move constructer which you can't do because it's being called internally by _books.erase(). So you need the Book class to hold a copy of it.

    For this solution to work you also need to make _ID in the Author class non const otherwise Author can't provide a default constructor which is necessary for the std::move.

    And a little side note return _isbn == other._isbn does not actually compare the values of _isbn and other._isbn but rather if they are the same pointer, which they will never be since Library constructs it's own books. To compare the actual values of _isbn and other._isbn use:

    bool operator==(const Book& other) const {
        return strcmp(_isbn, other._isbn) == 0;
    }