Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a reference to an object (from an unordered_map), when the key may not exist?

Tags:

c++

c++11

Say I have an Object:

class Object{
public:
Object(std::vector<int>stuff){

    }
}

Each of these objects is only accessible from a class Foo:

class Foo{
public:
std::unordered_map<int,Object> _objects;

bool getObjectForId(const int& objectId,Object& rep){
     bool found = false;
     std::unordered_map<int, Object>::const_iterator got = _objects.find(objectId);
     if(got != _objects.end()){
        found = true;
        rep = _objects[objectId];
     }
     return found;
}

In some other class I will try to get a reference to an object by doing:

class Other{
private:
   Foo myFoo;
public:

   void changeSomeObjectProperty(const int& objectId){
       Object rep;  
       bool gotIt = myFoo.getObjectForId(objectId,rep);

       //Then I will do some stuff with the rep, if gotIt is true
   }
}

Does this pattern make sense ? I do not want a copy of the object. I want a reference to the object, but I am trying to avoid using pointers...

like image 660
Rahul Iyer Avatar asked Dec 05 '16 08:12

Rahul Iyer


Video Answer


2 Answers

I'd plump for boost::optional as it conforms to the direction in which idiomatic C++ code is heading.

It will be adopted into the C++ standard from C++17 onwards as std::optional. For more details, see http://en.cppreference.com/w/cpp/utility/optional.

If you're reluctant to use the boost library or the timescales in migrating your toolchain to a C++17 standards compliant compiler are too long, then you could handcode the relevant functionality of std::optional in a few lines of code.

like image 176
Bathsheba Avatar answered Oct 07 '22 17:10

Bathsheba


Returning a non-owning pointer is perfectly reasonable and idiomatic. Treating pointers as "references to data someone else owns that could not exist" is a reasonably pattern.

An alternative is boost::optional<T&>, but that is basically a pointer, and C++17 std::optional last I checked did not support optional references.

std::experimental::observer_ptr<T> is another option, or writing your own, if you want to be extremely clear that your T* is not-owning. An observer_ptr<T> is basically a boost::optional<T&> I believe.

like image 23
Yakk - Adam Nevraumont Avatar answered Oct 07 '22 17:10

Yakk - Adam Nevraumont