Search code examples
c++referencestdoptional

optional refence to an object: best way?


I want a function to return an optional reference to an object. Idea is to avoid copy, but seems like i should not be using according to this discussion: std::optional specialization for reference types

Lets say I have a map of objects, and I want my function to return a reference to an object, if it is exists in the map. What is the best way?

struct HeavyObj;
std::map<int, HeavyObj> my_map;

std::optional<HeavyObj&> get_obj(int key){   
    if(auto it = my_map.find(key); it != my_map.end()){
        return std::optional<HeavyObj&>{ ? };
    } else {
        return {};
    }

ps: needed for C++17

update, If I use a pointer, I get:



#include <optional>
#include <map>
struct HeavyObj{
    int data;
};
static std::map<int, HeavyObj> my_map;

std::optional<HeavyObj*> get_obj(int key){   
    if(auto it = my_map.find(key); it != my_map.end()){
        return std::optional<HeavyObj*>{&(*it)};
    } else {
        return {};
    }
}

int main(){
    auto test  = get_obj(3);
    return 0;
}

// gcc -std=c++17 -Wall optional.cc -lstdc++
optional.cc: In function ‘std::optional<HeavyObj*> get_obj(int)’:
optional.cc:13:47: error: no matching function for call to ‘std::optional<HeavyObj*>::optional(<brace-enclosed initializer list>)’
   13 |         return std::optional<HeavyObj*>{&(*it)};
      |                                               ^
    ```

Solution

  • As mentioned, you can use the fact that an uninitialized pointer is nullptr to mimic the optional behavior.

    However, some people might consider it cleaner to use optional anyway as it is more consistent if you have a similar function returning an optional int for instance.

    You can use the std::nullopt when the value is not found and simply return the value if it is found (the compiler will do the cast from HeavyObject* to optional<HeavyObject*> but you can do it manually).