Skip to main content
Code Review

Return to Question

Notice removed Draw attention by MivVG
Bounty Ended with gyre's answer chosen by MivVG
Notice added Draw attention by MivVG
Bounty Started worth 50 reputation by MivVG
Tweeted twitter.com/StackCodeReview/status/997697574193778688
it's means "it is"; its is the pronoun
Source Link
JDługosz
  • 11.7k
  • 19
  • 40

The items are stored in a std::unordered_map<std::string, std::pair<std::unique_ptr<Item>, unsigned>>; I will break down why I chose for this. First of all, I wanted the items to be accessible in some way. Iterators were clumsy, because they would invalidate when an item is added to the inventory. I still kept the begin() and end() functions for if you would want to iterate through an inventory in a loop. So I chose for an undoredered map, with string indices so you can give every item it'sits own string ID. The items are stored as a pair of [Item, Count], since I wanted to be able to stack items where possible (Item.stackable() == true).

The items are stored in a std::unordered_map<std::string, std::pair<std::unique_ptr<Item>, unsigned>>; I will break down why I chose for this. First of all, I wanted the items to be accessible in some way. Iterators were clumsy, because they would invalidate when an item is added to the inventory. I still kept the begin() and end() functions for if you would want to iterate through an inventory in a loop. So I chose for an undoredered map, with string indices so you can give every item it's own string ID. The items are stored as a pair of [Item, Count], since I wanted to be able to stack items where possible (Item.stackable() == true).

The items are stored in a std::unordered_map<std::string, std::pair<std::unique_ptr<Item>, unsigned>>; I will break down why I chose for this. First of all, I wanted the items to be accessible in some way. Iterators were clumsy, because they would invalidate when an item is added to the inventory. I still kept the begin() and end() functions for if you would want to iterate through an inventory in a loop. So I chose for an undoredered map, with string indices so you can give every item its own string ID. The items are stored as a pair of [Item, Count], since I wanted to be able to stack items where possible (Item.stackable() == true).

added explanations requested in comments
Source Link
MivVG
  • 205
  • 2
  • 12

EDIT: as per request in the comments, here are some further explanations:

Architecture

As I created this project with portability across other projects in mind, so as a kind of library, the architecture is designed to be as simple to use as possible. All Items will be inherited from a base IItem class, or any other class that supports the functions in the Inventory::Traits class. The inventory is responsible for managing the resources of every item, and for creating them. So when adding an item you call

inventory.emplaceItem<SomePotion>("Potion", 50); //the 50 is passed to SomePotion's constructor

MAX_SIZE

MAX_SIZE is a template parameter due to an unlucky design choice at the very beginning. Since I did not want to do lots of allocations for items, I wanted to have the size fixed. This is probably completely unneccesary, but annoying to remove now.

Item usage

Since the Inventory is responsible for using the items (by calling useItem("name", target_ptr);), I needed some way of doing that. I chose for the Visitor Pattern, which I implemented with the ItemDispatcher class.

Data Structure

The items are stored in a std::unordered_map<std::string, std::pair<std::unique_ptr<Item>, unsigned>>; I will break down why I chose for this. First of all, I wanted the items to be accessible in some way. Iterators were clumsy, because they would invalidate when an item is added to the inventory. I still kept the begin() and end() functions for if you would want to iterate through an inventory in a loop. So I chose for an undoredered map, with string indices so you can give every item it's own string ID. The items are stored as a pair of [Item, Count], since I wanted to be able to stack items where possible (Item.stackable() == true).

Reusability

About the reusable in multiple projects. With that I mean that if I, at some point decide to make an RPG game, and the character needs an inventory, that I can just use this exact Inventory class without any modifications. If I then later want to make another, completely different game that also features an Inventory, or some other way of storing items, I can reuse this again.

Techniques

The Traits class is used as a wrapper for the SFINAE type traits that I use to detect if an eventual custom Item type supports all required functions, set for example like:

Inventory<200, MyCoolGameObject, MyCoolItem> inventory;

Traits is a class because I can't do

class X
{
 namespace Y
 {
 };
};

EDIT: as per request in the comments, here are some further explanations:

Architecture

As I created this project with portability across other projects in mind, so as a kind of library, the architecture is designed to be as simple to use as possible. All Items will be inherited from a base IItem class, or any other class that supports the functions in the Inventory::Traits class. The inventory is responsible for managing the resources of every item, and for creating them. So when adding an item you call

inventory.emplaceItem<SomePotion>("Potion", 50); //the 50 is passed to SomePotion's constructor

MAX_SIZE

MAX_SIZE is a template parameter due to an unlucky design choice at the very beginning. Since I did not want to do lots of allocations for items, I wanted to have the size fixed. This is probably completely unneccesary, but annoying to remove now.

Item usage

Since the Inventory is responsible for using the items (by calling useItem("name", target_ptr);), I needed some way of doing that. I chose for the Visitor Pattern, which I implemented with the ItemDispatcher class.

Data Structure

The items are stored in a std::unordered_map<std::string, std::pair<std::unique_ptr<Item>, unsigned>>; I will break down why I chose for this. First of all, I wanted the items to be accessible in some way. Iterators were clumsy, because they would invalidate when an item is added to the inventory. I still kept the begin() and end() functions for if you would want to iterate through an inventory in a loop. So I chose for an undoredered map, with string indices so you can give every item it's own string ID. The items are stored as a pair of [Item, Count], since I wanted to be able to stack items where possible (Item.stackable() == true).

Reusability

About the reusable in multiple projects. With that I mean that if I, at some point decide to make an RPG game, and the character needs an inventory, that I can just use this exact Inventory class without any modifications. If I then later want to make another, completely different game that also features an Inventory, or some other way of storing items, I can reuse this again.

Techniques

The Traits class is used as a wrapper for the SFINAE type traits that I use to detect if an eventual custom Item type supports all required functions, set for example like:

Inventory<200, MyCoolGameObject, MyCoolItem> inventory;

Traits is a class because I can't do

class X
{
 namespace Y
 {
 };
};
added an explanation for the git link
Source Link
MivVG
  • 205
  • 2
  • 12

Note: I have just read a meta post that says that it is not allowed to post GitHub links. I am not sure what I should do in this case, as I mostly want the Inventory header reviewed. The files in the github repo are only for when there really is more information required.

Note: I have just read a meta post that says that it is not allowed to post GitHub links. I am not sure what I should do in this case, as I mostly want the Inventory header reviewed. The files in the github repo are only for when there really is more information required.

Source Link
MivVG
  • 205
  • 2
  • 12
Loading
lang-cpp

AltStyle によって変換されたページ (->オリジナル) /