How do I get my map to work in my class for my inventory system?

So Im just testing out how to use maps for an inventory system and It seems like theres a problem with using a class as an argument, what am i doing wrong? I wrote this code just to test out the map using an inventory system, this is not something im actually working on, its simply just thrown together to quickly test out how to use the map. Line 35 is the problem line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <map>
#include <string>

using std::string;
using std::map;
using std::cout;
using std::pair;

void MapExampleOne();

class Item
{
    public:
        Item(const string& name, int size): mName(name), mSize(size)
        {}

        string GetName() const { return mName; }
        int GetSize() const { return mSize; }

    private:
        string mName{ "Item" };
        int mSize{ 0 }; //Slots this item uses in the inventory.
};

class Container
{
    public:
        Container(const string& name, int slots): mName(name), mSlots(slots)
        {}

        void Add(Item& item, int amount)
        {
            //This is the problem line!
            mContainer.insert(pair<Item, int>(item, amount));
        }

        string GetName() const { return mName; }
        int GetSlots() const { return mSlots; }

    private:
        string mName{ "Container" };
        int mSlots{ 0 };
        map<Item, int> mContainer;
};

int main()
{
    //MapExampleOne();

    Item Map("Map", 4);
    Item SmallMedkit("Small Medkit", 2);
    Item Handgun("Handgun", 6);
    Item Key("Key", 2);

    cout << "ITEMS" << "\n\n";

    cout << "Item Name: " << Map.GetName() << " - Size: " << Map.GetSize() << '\n';
    cout << "Item Name: " << SmallMedkit.GetName() << " - Size: " << SmallMedkit.GetSize() << '\n';
    cout << "Item Name: " << Handgun.GetName() << " - Size: " << Handgun.GetSize() << '\n';
    cout << "Item Name: " << Key.GetName() << " - Size: " << Key.GetSize() << '\n';

    Container PlayerInventory("Player Inventory", 30);

    cout << "\nCONTAINERS" << "\n\n";

    cout << "Container Name: " << PlayerInventory.GetName() << '\n';
    cout << "Container Size: " << PlayerInventory.GetSlots() << '\n';
}

void MapExampleOne()
{
    map<string, int> inventory;

    inventory.insert(pair<string, int>("1911", 34));
    inventory.insert(pair<string, int>("M4", 150));
    inventory.insert(pair<string, int>("Rocket Launcher", 8));

    map<string, int>::iterator itr = inventory.begin();

    if (inventory.size() < 1)
    {
        cout << "Inventory is empty, fill it with something first!\n";
    }
    else
    {
        for (itr = inventory.begin(); itr != inventory.end(); ++itr)
        {
            cout << "Name: " << itr->first << " - Ammo: " << itr->second << '\n';
        }
    }
}


Errors:

Severity	Code	Description	Project	File	Line	Suppression State
Error	C2676	binary '<': 'const _Ty' does not define this operator or a conversion to a type acceptable to the predefined operator	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::multimap<_Kty,_Ty,_Pr,_Alloc> &,const std::multimap<_Kty,_Ty,_Pr,_Alloc> &)': could not deduce template argument for 'const std::multimap<_Kty,_Ty,_Pr,_Alloc> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::map<_Kty,_Ty,_Pr,_Alloc> &,const std::map<_Kty,_Ty,_Pr,_Alloc> &)': could not deduce template argument for 'const std::map<_Kty,_Ty,_Pr,_Alloc> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::tuple<_Types...> &,const std::tuple<_Types...> &)': could not deduce template argument for 'const std::tuple<_Types...> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(std::nullptr_t,const std::unique_ptr<_Ty,_Dx> &)': could not deduce template argument for 'const std::unique_ptr<_Ty,_Dx> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,std::nullptr_t)': could not deduce template argument for 'const std::unique_ptr<_Ty,_Dx> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,const std::unique_ptr<_Ty2,_Dx2> &)': could not deduce template argument for 'const std::unique_ptr<_Ty,_Dx> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(std::nullptr_t,const std::shared_ptr<_Ty> &) noexcept': could not deduce template argument for 'const std::shared_ptr<_Ty> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::shared_ptr<_Ty> &,std::nullptr_t) noexcept': could not deduce template argument for 'const std::shared_ptr<_Ty> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::shared_ptr<_Ty> &,const std::shared_ptr<_Ty0> &) noexcept': could not deduce template argument for 'const std::shared_ptr<_Ty> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *const )': could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const _Elem *const ,const std::basic_string<_Elem,_Traits,_Alloc> &)': could not deduce template argument for 'const _Elem *const ' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &) noexcept': could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::move_iterator<_Iter> &,const std::move_iterator<_Iter2> &)': could not deduce template argument for 'const std::move_iterator<_Iter> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::reverse_iterator<_BidIt> &,const std::reverse_iterator<_BidIt2> &)': could not deduce template argument for 'const std::reverse_iterator<_BidIt> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117	
Error	C2784	'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)': could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const _Ty'	Map Examples	C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\xstddef	117

Last edited on
the map key has to be sortable. So you need to provide a comparison operator for the item class if you want it to be the key.
alternately you can use unordered map.
Last edited on
How would that look in code? Im a little confused on how to order the keys using the operator<.

Also do I really NEED to make the map part of the container class? I'm not against it im just wondering if thats a good way to do it.
Last edited on
Whether you need or not is up to you. (I.e. we do not know what data&operations you will need in the application.)

For unordered map option, update line 44 to be:
unordered_map<Item, int> mContainer;


For comparison operator there are two approaches.

Before that, your Item contains a string and int. If we can trust that you won't create:
1
2
Item small( "Axe", 2 );
Item large( "Axe", 3 );

i.e. that each Item will have unique name, then it should be enough to sort the Items by name.

The option one is to let the std::map use the default comp (the std::less).
That will call bool operator< (const Item&, const Item& );, so do provide one:
1
2
3
4
bool operator< (const Item& lhs, const Item& rhs)
{
  return lhs.GetName() < rsh.GetName();
}

(If you do not have unique names, then do add the slots into that.)

The option two is to give a comp to the map. First create ItemComp:
1
2
3
4
struct ItemComp {
  bool operator() (const Item& lhs, const Item& rhs) const
  {return lhs.GetName() < rsh.GetName();}
};

Then update the line 44 into:
map<Item, int, ItemComp> mContainer;

See https://cplusplus.com/reference/map/map/map/
Option one is what i wasa thinking, im not sure though, im going to need to study how to use the operator keyword more but when I paste that code for option one into my Item class it says:

Severity	Code	Description	Project	File	Line	Suppression State
Error (active)	E0344	too many parameters for this operator function	Map Examples	C:\Users\Chay\source\repos\Map Examples\Map Examples\Map Examples.cpp	21	
Error	C2804	binary 'operator <' has too many parameters	Map Examples	C:\Users\Chay\source\repos\Map Examples\Map Examples\Map Examples.cpp	22	
Error	C2333	'Item::operator <': error in function declaration; skipping function body	Map Examples	C:\Users\Chay\source\repos\Map Examples\Map Examples\Map Examples.cpp	22	

i actually had something like this before i posted this issue on here, because I knew that i would need to use the operator keyword but i got that same eror as above so i figured i was doing it wrong and deleted the code and posted here, so I did do it right its just not working for whatever reason.

It seems like the operator error is saying that the left hand side is implicit so i only need to define rhs but i still get an error :/

Severity	Code	Description	Project	File	Line	Suppression State
Error	C2678	binary '<': no operator found which takes a left-hand operand of type 'const _Ty' (or there is no acceptable conversion)	Map Examples	


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Item
{
    public:
        Item(const string& name, int size): mName(name), mSize(size)
        {}

        bool operator< (const Item& rhs)
        {
            return mName < rhs.GetName();
        }

        string GetName() const { return mName; }
        int GetSize() const { return mSize; }

    private:
        string mName{ "Item" };
        int mSize{ 0 }; //Slots this item uses in the inventory.
};
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <string_view>
#include <compare>
#include <map>
#include <iomanip>

struct item
{
    std::string name ; // key
    std::size_t n_slots = 1 ; // number of slots

    explicit item( std::string_view name, std::size_t n_slots = 1 ) : name(name), n_slots(n_slots) {}

    // compare items based on name (ignore n_slots). TO DO: make these comparisons case insensitive?
    // see: https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/
    auto operator <=>( const item& that ) const noexcept { return this->name <=> that.name ; } // key comp
    auto operator <=>( std::string_view name ) const noexcept { return this->name <=> name ; } // for transparent key lookup
};

int main()
{
    static_assert( __cpp_lib_generic_associative_lookup	== 201304L) ; // allow transparent lookups in map

    // map item => amount; std::less<> is a transparent comparator
    // see: https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
    std::map< item, std::size_t, std::less<> > container
    {
        { item{ "Small Medkit", 2 }, 5 },
        { item{ "Handgun", 4 }, 3 },
        { item{ "Key", 1 }, 8 }
    };

    container.emplace( item{"Rifle",9}, 1 ) ; // insert a new item into the map

    // modify an item: add two more Handguns (increase amount by two)
    if( const auto iter = container.find( "Handgun" ) ; iter != container.end() ) iter->second += 2 ;

    for( std::string name : { "Small Medkit", "Camera", "Rifle", "Handgun", "Book", "Key" } )
    {
        std::cout << '\n' << std::quoted(name) << "  --  " ;

        if( const auto iter = container.find(name) ; iter != container.end() )
            std::cout << "num slots: " << iter->first.n_slots << ",  amount: " << iter->second << '\n' ;

        else std::cout << " *** not present in map ***\n" ;
    }
}

http://coliru.stacked-crooked.com/a/9336168bd71e1db8

It seems like the operator error is saying that the left hand side is implicit so i only need to define rhs but i still get an error :/

Error	C2678	binary '<': no operator found which takes a left-hand operand of type 'const _Ty' 


The bool operator< (const Item& lhs, const Item& rhs); that I wrote is a standalone function, not a member.

The operator can be a member too. Note the const _Ty in your error message. You should have written:
1
2
3
4
5
6
7
class Item
{
public:
  bool operator< (const Item& rhs) const;

  // other members
};

because the operator< does not modify *this and therefore should be allowed to be called on const Items (like the map does).

Additionally, since your op is a member, it has direct access to class members and could be implemented:
1
2
3
4
bool Item::operator< (const Item& rhs) const
{
  return mName < rhs.mName;
}
Last edited on
Ah ok, its supposed to be standalone, thats what was messing me up, so I had it right when i did it, I just put it in the wrong spot. Thank you! It works now.
Topic archived. No new replies allowed.