2

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.

JeJo
  • 30,635
  • 6
  • 49
  • 88
quazi_moto
  • 449
  • 1
  • 3
  • 14
  • For some reason, my question is not displaying properly. The map key is an object type, and the map value is an int type. – quazi_moto Sep 22 '18 at 06:35
  • You need an `operator<<()` for the type the maps key is of. – Swordfish Sep 22 '18 at 06:36
  • Do I still include std::ostream& as a parameter? – quazi_moto Sep 22 '18 at 06:41
  • `std::ostream& operator<<(std::ostream &os, WhateverYourType const &wyt);` – Swordfish Sep 22 '18 at 06:53
  • I think that's what I did in this line: std::ostream& operator<<(std::ostream& outstream, Inventory& inv) No? Inv is a pointer to an Inventory object. – quazi_moto Sep 22 '18 at 07:04
  • "You need an operator<<() **for the type the maps key is of**" – Swordfish Sep 22 '18 at 07:05
  • To answer this properly, you should expose more code. What is `Inventory`? Form your exposed code, it seems to have a member variable `Inventory::inventory` which seems to be a container. This doesn't answer why it should have a `first` and `second`. Please, make a [mcve] and [edit] it into your question if you want a sufficient answer. – Scheff's Cat Sep 22 '18 at 07:27
  • My key type is a class called Auto_Part. I'm going to edit the original post to show you how I've changed it. I'm still getting the same error. – quazi_moto Sep 22 '18 at 07:27
  • 1
    I really wonder why this question got two upvotes where other questions with proper problem description and MCVE got down-votes simply because they presented beginner problems. – Scheff's Cat Sep 22 '18 at 07:29
  • Please, consider the **Complete** in [mcve]. Complete means, I can copy/paste your code to an online compiler and try by myself. – Scheff's Cat Sep 22 '18 at 07:30
  • Sorry, for not being complete. I tried to be minimal. I am editing the post now. – quazi_moto Sep 22 '18 at 07:37

2 Answers2

1

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.

Avert
  • 435
  • 3
  • 17
1

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
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • I tried this, and this is the error I'm getting: error: invalid range expression of type 'Inventory'; no viable 'begin' function available for(auto p : inv){ – quazi_moto Sep 22 '18 at 07:10
  • 1
    The above code is right. I figured out the problem wasn't with the printing, it was with the map. Because maps are sorted, and I was trying to sort objects, I had to define how to sort objects by overloading the operator<. – quazi_moto Sep 24 '18 at 20:31