quazi_moto
quazi_moto

Reputation: 479

Printing a map of object, which has another object as Key

I am trying to print the contents of my map <Object, int>. Here is the code in question:

void Inventory::print_initial_inventory()
{
    for(auto p : inventory) {
        std::cout << p.first << " : " << p.second << std::endl;
    }
}

std::ostream& operator<<(std::ostream& outstream, Inventory& inv) 
{
    outstream << inv.first << "\nNumber of parts: " << inv.second << std::endl;
    return outstream;
}

I know the problem is at p.first? because std::cout doesn't know how to print an object, so I tried to overload the operator<< , but I'm not sure how to do it. Can anyone point me in the right direction?

EDIT Here's how I've tried the problem again. I was suggested to pass the key type to the operator<< overload. Here is my code now:

void Inventory::print_initial_inventory()
{
    for(auto x : inventory) {
        std::cout << x.first << " : " << x.second << std::endl;
    }
}

std::ostream& operator<<(std::ostream& outstream, Auto_Part& inv)
{
    outstream << "Type: " << inv.type << "\nName: " << inv.name << "\nPart Number: " << inv.part_number << "\nPrice: $" << inv.price << std::endl;
    return outstream;
}

I'm still getting an invalid binary expression error pointing to x.first.

Upvotes: 2

Views: 101

Answers (2)

JeJo
JeJo

Reputation: 32852

I know the problem is at p.first? because std::cout doesn't know how to print an object, so I tried to overload the << operator, but I'm not sure how to do it.

The basics of operator overloading can be found in this post: What are the basic rules and idioms for operator overloading? I strongly recommend to read this before you step further

In your case I found two basic issues:

  1. You have not mentioned your Key class a lot. Especially, how would you insert the element to the std::map(member of Inventory class), if you do not provide operator<? Since Key class is a user-defined you need to give one. You can read more about it in this SO post:std::maps with user-defined types as key
  2. Second and main issue of your code is, not providing a operator<< for your Key type. That can be done as follows:

For instance, let's say class Key

class Key
{
    int member;
public:
    Key(const int a): member(a){}
    // provide operator< for your Key type
    bool operator<(const Key& other)const { return this->member < other.member; }
   // provide operator<< for Key class like follows
    friend std::ostream& operator<<(std::ostream& out, const Key& key);
};
// implement outside the class
std::ostream& operator<<(std::ostream& out, const Key& key)
{
    // simply for this case
    return out << key.member;
}

and now you can provide operator<< for Inventory class in a similar manner.

SEE LIVE EXAMPLE

// now in Inventory class
class Inventory
{
   std::map<Key, int> inventory;
public:
    Inventory(const std::map<Key, int>& m): inventory(std::move(m)) {}
    // declared as friend, so that you can access the private member(map)
    friend std::ostream& operator<<(std::ostream& out, const Inventory& inv);
};
// implement outside the class
std::ostream& operator<<(std::ostream& out, const Inventory& inv)
{
    for(const auto& entry: inv.inventory )
        out << entry.first << " Number of parts: " << entry.second << std::endl;
    return out;
}
// in the main
int main()
{
    Key key1{1};
    Key key2{2};
    std::map<Key, int> tempInvObj{{key1, 11}, {key2, 12}};
    Inventory obj{tempInvObj};
    std::cout << obj;
    return 0;
}

Output:

1 Number of parts: 11
2 Number of parts: 12

Upvotes: 1

Avert
Avert

Reputation: 445

std::cout is std::ostream object. std::ostream has operator<< overloaded by standard for some basic types (you can check them out here). If you want to be able to use operator<< with your class (let's say class MyType), you have to overload that operator by yourself.

For built-in C++ types like std::ostream you perform such overloading outside class (because otherwise you'd have to modify std::ostream), and the syntax for that is:

std::ostream& operator<< (std::ostream& s, const MyType& arg)
{
    /* enter you implementation here */
    return s;
}

More info can be found here.

Upvotes: 1

Related Questions