简体   繁体   中英

Lazy argument evaluation for try_emplace?

Im in need of an object that can wrap a lazy initialization for a try_emplace with map (in effect calling a factory type of function only when needed), so that the following will convert ok in try_emplace :

std::map<std::string, bool> cache_;
cache_.try_emplace("hello", lazy_wrapper([]{return true;}));

or perhaps

std::map<std::string, whatever_wrapper<bool> > cache_;
cache_.try_emplace("hello", []{return true;});

I imagine that should be possible, but mainly on the lookout for an off-the-shelf solution (eg. std / boost ) compared to rolling my own wrapper.

The following is a hand-made solution i just threw together in a few minutes, that does the job, but Im mostly on the lookout for some kind of off-the-shelf solution:

template<class F>
struct lazy_wrap {
    F f_;
    lazy_wrap(F&& f) : f_(f) {}
    template<class T>
    operator T() {
        return f_();
    }
};

You ultimately will have to implement the try-emplace logic yourself, since there's no simple function to do it.

template<typename Map, typename Key, typename Func>
auto lazy_try_emplace(Map &map, const Key &key, Func f)
{
    auto it = map.find(key);
    if(it == map.end())
      return map.emplace(key, f());
    return std::pair(it, false);
}

Yes, this looks up the element twice, but there's no way to avoid that without actually being part of the std::map implementation (which is why try_emplace exists at all). Search time could be minimized by replacing map.find with map.lower_bound , changing the conditional test to see if the key is not equal to key , and using emplace_hint with that iterator.

Do you really need a wrapper? You could do this instead:

// C++20
if (!cache_.contains("hello"))
    cache_.emplace("hello", [] { return true; });

// pre C++20
if (cache_.count("hello") == 0)
    cache_.emplace("hello", [] { return true; });

Simple, clear, no headache.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM