What to return when std :: map :: at go out_of_range?

In the game, I would like to find a map of objects and return the one that is on a certain square of the board. But what if the square is empty? (Elements are not stored in the board structure. Do not pay attention to this for the purposes of this question.) I have the code below, but what should I do to return an β€œempty” link?

map<pair<int, int>, Item*> _items; Item& itemAt(int row, int col) const { try { return *_items.at(make_pair(row, col)); } catch(out_of_range& e) { return // what goes here? } } 

Or is this the wrong approach and should I just use find() ?

+8
c ++ exception c ++ 11
source share
4 answers

In this case, it is useful to use a pointer as a means to represent "zero or one object":

 Item* itemAt(int row, int col) const { try { return _items.at(make_pair(row, col)); } catch(out_of_range& e) { return nullptr; } } 

However, using std::map::find() is probably a faster and more understandable approach.

+9
source share

If you do not find the element, this is not a condition for an error in your program, you should not return the link (since links cannot be empty). Rather, you should return a pointer (not owning, most likely) and return nullptr if the item was not found:

 Item* itemAt(int row, int col) const { try { return _items.at(make_pair(row, col)); } catch(out_of_range& e) { return nullptr; } } 

On the other hand, if the search for an element is not an error, then you can return the link (when the element is found) and allow the exception to be thrown when the element is not found - the responsibility for processing it will belong to that part of your code that has strategic knowledge of how handle it:

 Item& itemAt(int row, int col) const { return *_items.at(make_pair(row, col)); } 
+12
source share

If the client code requests an item that does not exist, then the throw exception will report an error and return Item& .

If this is not an error, since the value_type from the map already Item* changes the return type as Node* and returns nullptr to indicate that the item does not exist in the requested position and use map::find() .

To avoid life expectancy problems that already exist with the Item& return type, consider changing the value_type to std::shared_ptr<Item> . If the client code has a link or a raw pointer to a value using map , and this element is removed from map , then the client remains with a dangling pointer / link. Going to std::shared_ptr<Item> avoids this scenario. The itemAt() function will return the value std::shared_ptr<Item> . This also has the advantage that the Item in the map does not have to be explicitly delete d.

+3
source share

In fact, other people had the same problem:

  • some of them wrote boost::optional
  • you can return a pair of pointers and return a value
  • you can throw an exception
  • you can return a null object
+1
source share

All Articles