Vector of user-defined types

closed account (S1URSL3A)
I'm fairly new to C++ and I'm currently in the process of learning it.
I'm writing a text adventure game (using Visual Studio 2019) where the user types in what they want to do (e.g. "go south," "get sword," etc.). I'm using a vector "inv" of my struct "item" for the player's inventory. I want it to be where the user enters "drop" followed by the name of the item they want to drop, and the item gets erased from their inventory (after first being added to the room's vector of items). But when I tried to implement this, I got a compile-time error with this message:

Error C2280 'item &item::operator =(const item &)': attempting to reference a deleted function TextAdventure C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.20.27508\include\xutility 2086

Using multi-line commenting, I narrowed it down to every statement where I call the vector's "begin()" member function. Here is an example:
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
#include <iostream>
#include <vector>

struct item {

	const std::string name{},desc{};
};

struct room {

	const std::string name{},desc{};
	std::vector<item> cont{};
};

std::vector<item> inv{{"sword","(sword desc)"},{"lantern","(lantern desc)"}};

room exampleRoom{{"kitchen"},{"(kitchen description)"},{}};

int main() {

	std::string word{};
	std::cin >> word;

	for (char i{0}; i < inv.size(); ++i)
		if (inv[i].name == word) {

			exampleRoom.cont.push_back(inv[i]);
			
			// The error stops when I comment out the following line:
			inv.erase(inv.begin() + i);

			std::cout << "The " << word << " is now on the ground.\n";
		}
}

Does the error occur because the vector contains user-defined types? How can I get this to work? Any help would be greatly appreciated. Thanks.
Last edited on
You need to break out of the loop after you move the item. Also, don't put {} after std::string or std::vector declarations. They are initialized by default. And don't use char as an index to a vector. Use an int at least. It's probably most correct to use size_t.

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
#include <iostream>
#include <vector>

struct item {
    std::string name,desc;
};

std::ostream& operator<<(std::ostream& os, const item& it) {
    return os << it.name << " : " << it.desc;
}

struct room {
    std::string name, desc;
    std::vector<item> cont;
};

std::vector<item> inv{
    { "sword",   "(sword desc)" },
    { "lantern", "(lantern desc)" }
};

room exampleRoom{
    {"kitchen"}, {"(kitchen description)"}, {}
};

int main() {

    std::string word;
    std::cin >> word;

    for (size_t i{0}; i < inv.size(); ++i)
        if (inv[i].name == word) {
            exampleRoom.cont.push_back(inv[i]);
            inv.erase(inv.begin() + i);
            std::cout << "The " << word << " is now on the ground.\n";
            break;
        }

    std::cout << "\nInventory:\n";
    for (const item& it: inv) std::cout << it << '\n';
    std::cout << "\nRoom:\n";
    for (const item& it: exampleRoom.cont) std::cout << it << '\n';
}

closed account (S1URSL3A)
Okay, so I did the things you said to do:

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
#include <iostream>
#include <vector>
struct item {

	const std::string name,desc;
};

struct room {

	const std::string name,desc;
	std::vector<item> cont;
};

std::vector<item> inv{{"sword","(sword description)"},{"shield","(shield description)"}};
room exampleRoom{{"kitchen"},{"(kitchen description)"},{}};

int main() {

	std::string word{};
	std::cin >> word;

	for (size_t i{0}; i < inv.size(); ++i)
		if (inv[i].name == word) {

			exampleRoom.cont.push_back(inv[i]);
			inv.erase(inv.begin() + i);

			std::cout << "The " << word << " is now on the ground.\n";
			break;
		}
}

But I'm still getting the same error.
I forgot to mention that I also removed the "const" on your strings.
The erase method of std::vector needs to be able to copy the items to new positions (like removing an element from an array). So it needs the operator= method of item. But making the strings const causes the operator= method to be "deleted" so you don't get the default method.
Last edited on
closed account (S1URSL3A)
That did it! Thank you so much for your help! I'll be sure to keep those in mind for the future. There's one other thing I could use some help with. How can I use std::sort() to sort the inventory by item name?
Last edited on
The sort has a version that takes third argument:
http://www.cplusplus.com/reference/algorithm/sort/

For example:
1
2
3
sort( inv.begin(), inv.end(),
      [](auto& lhs, auto& rhs){return lhs.name < rhs.name;}
    );
closed account (S1URSL3A)
Thank you, everyone, for all your help!
Topic archived. No new replies allowed.