Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to return when a std::map::at goes out_of_range?

In a game I would like to search a map of items and return the one located on a particular square of the board. But what if the square is empty? (The items are not stored in the board structure. Never mind about that for the purposes of this question.) I have the code below, but what should I do to return an "empty" reference?

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 I should just use find()?

like image 763
Jaldhar Avatar asked May 27 '13 13:05

Jaldhar


People also ask

What does map at return?

The C++ function std::map::at() returns a reference to the mapped value associated with key k.

What does map return if key not found C++?

Return Value: The function returns an iterator or a constant iterator which refers to the position where the key is present in the map. If the key is not present in the map container, it returns an iterator or a constant iterator which refers to map. end().

What is std :: Out_of_range?

Defines a type of object to be thrown as exception. It reports errors that are consequence of attempt to access elements out of defined range.

Does map at throw an error?

C++ map at() function is used to access the elements in the map with the given key value. It throws an exception out_of _range, if the accessed key is not present in the map.


2 Answers

If not finding an item is not an error condition in your program, then you should not return a reference (since references cannot be null). Rather, you should return a (non-owning, most likely) pointer, and return nullptr in case 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 not finding an item is an error, then you can return a reference (when the item is found) and let the exception propagate when the item is not found - the responsibility of handling it would belong to the part of your code that has strategic knowledge on how to handle it:

Item& itemAt(int row, int col) const {
    return *_items.at(make_pair(row, col));
}
like image 150
Andy Prowl Avatar answered Oct 18 '22 10:10

Andy Prowl


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

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 cleaner approach.

like image 22
Roland Levillain Avatar answered Oct 18 '22 09:10

Roland Levillain