C++ try_emplace的惰性参数评估?
我需要一个对象,该对象可以用map包装try_emplace的惰性初始化(实际上,只有在需要时才调用工厂类型的函数),以便在C++ try_emplace的惰性参数评估?,c++,c++17,C++,C++17,我需要一个对象,该对象可以用map包装try_emplace的惰性初始化(实际上,只有在需要时才调用工厂类型的函数),以便在try_emplace中转换为ok: std::map<std::string, bool> cache_; cache_.try_emplace("hello", lazy_wrapper([]{return true;})); std::映射缓存; cache.try_emplace(“hello”,lazy_包装器([]{return
try_emplace
中转换为ok:
std::map<std::string, bool> cache_;
cache_.try_emplace("hello", lazy_wrapper([]{return true;}));
std::映射缓存;
cache.try_emplace(“hello”,lazy_包装器([]{return true;}));
或许
std::映射缓存;
cache_u.try_uemplace(“hello”,[{return true;});
我想这应该是可能的,但主要是为了寻找一种现成的解决方案(例如,std/
boost
),而不是我自己的包装机。以下是我在几分钟内拼凑出来的一个手工解决方案,可以完成这项工作,但我主要是在寻找某种现成的解决方案:
template<class F>
struct lazy_wrap {
F f_;
lazy_wrap(F&& f) : f_(f) {}
template<class T>
operator T() {
return f_();
}
};
模板
结构惰性包装{
F_;
惰性包装(F&&F):F(F){}
模板
算子T(){
返回f_();
}
};
您真的需要包装器吗?您可以这样做:
// C++20
if (!cache_.contains("hello"))
cache_.emplace("hello", [] { return true; });
// pre C++20
if (cache_.count("hello") == 0)
cache_.emplace("hello", [] { return true; });
简单、清晰、不令人头痛。由于没有简单的功能,您最终必须自己实现try-emplace逻辑
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);
}
模板
自动延迟尝试模板(映射和映射、常量键和键、函数f)
{
auto it=map.find(键);
if(it==map.end())
返回map.emplace(键,f());
返回std::pair(it,false);
}
是的,这会查找元素两次,但是如果不真正成为
std::map
实现的一部分,就无法避免这种情况(这就是try\u emplace
存在的原因)。通过替换map.find
为map.lower\u bound
,更改条件测试以查看键是否不等于key
,并使用该迭代器使用emplace\u hint
。您尝试了什么?我尝试提供lambda裸体,即ofc。我没有编译。我想创建一个将要转换的类类型很容易,但正如我所说的,如果已经存在现成的解决方案,我最感兴趣。唉,在一个完美的(转发)世界里。就惰性而言,你的意思是除非键不在映射中,否则函数不会被调用吗?@Nicolas that Corrective这将每次计算f
以得到t
,我不会称之为“惰性”哦,这是针对std::map
,notstd::map
这是一个双重查找。正如你所说,我真的不需要一个包装器(map.find也可以),但这样一行代码更具表现力。同样的道理,我们一开始也不需要试射。
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);
}