3
votes

I want to use lazy loading of an unordered_map. I search the map for a key. If it exists I use the value. If it doesn't exist I create the value and emplace the key,value pair.

I want to avoid the last map.find() statement - it should be an unnecessary operation (performance is important). It might fail :-( and I'd hope for a better solution.

Note: The calling routine should only have a const reference to value. Avoid instantiation of value in calling routine.

How can I avoid the second lookup AND have a properly scoped const reference returned to the caller ?

h file

`    typedef std::vector DataPtrListVector;
    struct DataCacheStruct
    {
        DataPtrListVector dataItemOne;
    };
    typedef boost::unordered_map DataCacheMap;
    // declare instance variable
    DataCacheMap dataCacheMap;
    // declare function
    const DataCacheStruct& getOrCreateData( const std::string& dataKey,... );`

cpp file

`    // Lazy Load of DataStruct unordered_map
    std::string key = someString;
    const DataCacheStruct& dataStruct = getOrCreateData( key, ... );


    //
    const DataCacheStruct& class::getOrCreateData( const std::string key, ...)
    {
        DataCacheMap::const_iterator itData = dataCacheMap.find(key);
        if (itData != dataCacheMap.end())
        {
            return itData->second;
        }
        DataCacheStruct newData = doSomethingSlow();
        dataCacheMap.emplace(std::make_pair(key, newData));
        // Now I want to return newData as a const reference, as per unordered_map
        // but it goes out of scope before the calling routine can use it.
        DataCacheMap::const_iterator itData = dataCacheMap.find(key);
        return itData->second;
    }`
1
emplace returns the iterator where the element has been insertedBiagioF

1 Answers

2
votes

As I've already said, the method emplace, returns a pair of an iterator to the newly inserted element and a value of true.

You can simply use that iterator, to get a reference:

auto it_new_insertion = dataCacheMap.emplace(std::make_pair(key, newData));
if (it_new_insertion.second == false) {  
 // something wrong with memory. handle it
}
return it_new_insertion.first->second;