0

I have created two classes: Bank and Account.

I would like to use std::map<Bank, Account> bankAccount, like this:

bankAccount.insert(std::make_pair(bank1, account1));

but I get several compile-time errors.

I know how to use map<int, Bank> or map<int, Account>, but not map<Bank, Account>. I'm assuming the problem lies in telling the compiler how to ensure my Bank objects are unique, and since maps in C++ are ordered, I need to tell the compiler how to order the banks. This is no problem for the compiler if the key happens to be an integer.

My classes are as follows:

class Bank {
public:
    // Constructors
    Bank() = default;
    Bank(std::string name, std::string created, int balance, bool active)
            : m_name(std::move(name)), m_created(std::move(created)), m_balance(balance),   m_active(active) {};

    // Member functions
    void deposit(int amount) {
        m_balance += amount;
    }
    [[nodiscard]] int getBalance() const {
        return m_balance;
    }

    void setBalance(int amount) {
        m_balance = amount;
    }

    // Member attributes
    std::string m_name;
    std::string m_created;
    int m_balance{};
    bool m_active{};
};

class Account {
public:
    // Constructor
    Account() = default;
    Account(std::string name, int balance){
        m_name = name;
        m_balance = balance;
    }

    //Member functions
    void displayBalance() const {
        std::cout << m_name << ": " << m_balance << std::endl;
    }

    // Member attributes
    std::string m_name;
    int m_balance{};
};

A bank object is created as follows:

Bank bank1("FirstBank", "2015-01-01", 1000, true);

An account object is created as follows:

Account account1("Dining", 10000);

Can anyone please tell me how I can go about using my Bank class as a key to std::map?

I tried overloading operator<() in the Bank class as follows, but that didn't solve my problem:

bool operator<(Bank& other) {
    return m_name < other.m_name && m_created < other.m_created \
        && m_balance < other.m_balance && m_active < other.m_active;
}

Switching from std::map to std::unordered_map doesn't eliminate the compile-time errors, either.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

1 Answers1

0

Overloading operator< for your Bank class is the correct solution. However, your implementation of it is wrong, which will cause compile-time errors at best, and undefined behavior at runtime at worse.

Try something more like this instead:

class Bank {
public:
    ...

    bool operator<(const Bank& other) const {
        if (m_name < other.m_name)
            return true;
        if (m_name > other.m_name)
            return false;
        // m_name and other.m_name must be equal, keep comparing...

        if (m_created < other.m_created)
            return true;
        if (m_created > other.m_created)
            return false;
        // m_created and other.m_created must be equal, keep comparing...

        if (m_balance < other.m_balance)
            return true;
        if (m_balance > other.m_balance)
            return false;
        // m_balance and other.m_balance must be equal, keep comparing...

        return m_active < other.m_active;
    }
};

Alternatively:

class Bank {
public:
    ...
};

bool operator<(const Bank& b1, const Bank& b2)
{
    if (b1.m_name < b2.m_name)
        return true;
    // and so on, as shown above ...
}

Either way, the implementation of the operator can be greatly simplified by std::tie()'ing the values together, as std::tie already implements operator<, eg:

class Bank {
public:
    ...

    bool operator<(const Bank& other) const {
        return std::tie(m_name, m_created, m_balance, m_active) < std::tie(other.m_name, other.m_created, other.m_balance, other.m_active);
    }
}

Or:

class Bank {
public:
    ...
};

bool operator<(const Bank& b1, const Bank& b2) {
    return std::tie(b1.m_name, b1.m_created, b1.m_balance, b1.m_active) < std::tie(b2.m_name, b2.m_created, b2.m_balance, b2.m_active);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770