C++以迭代方式搜索混合类型地图



我有一大组 if 语句,我想变成一个循环:

if (intParams.find(paramName) != intParams.end()) {
return (float)intParams.at(paramName);
} else if (floatParams.find(paramName) != floatParams.end()) {
return (float)floatParams.at(paramName);
} else if (boolParams.find(paramName) != boolParams.end()) {
return (float)boolParams.at(paramName);
}
return defaultVal;

我想把它变成一个循环或折叠表达式来简化逻辑,但这很困难,因为intParams有类型Map<string, int64_t>,floatParams有类型Map<string, float>,而boolParams有类型Map<string, bool>。我试过查看提升,但找不到合适的东西。

我想将其简化为类似

for (auto& param : {intParams, floatParams, boolParams}) {
if (param.find(paramName) != param.end()) {
return (float)param.at(paramName);
}
}
return defaultVal;

让我知道我能做什么!

float retval=defaultVal;
auto all_maps = [&](auto&...maps){
auto one_map = [&](auto&map){
auto it = map.find(paramName);
if (it==map.end()) return false;
retval=static_cast<float>(it->second);
return true;
};
return ( one_map(maps) || ... );
};
all_maps(intParams, floatParams, boolParams);
return retval;

如果要避免分配默认值,可以使用可选。

还有一些 if constexpr 递归解决方案可以工作。

您可以使用折叠表达式和帮助程序类模板执行惊人的操作:

template<class T>
struct Search {
Search(const Map<std::string,T> &m,const std::string &k)
: m(m),k(k) {}  // for CTAD (until C++20)
friend std::optional<float> operator|(const std::optional<float> &f,const Search<U> &s) {
if(!f)
if(const auto i=s.m.find(s.k); i!=s.m.end())
return static_cast<float>(*i);
return f;
}
private:
const Map<std::string,T> &m;
const std::string &k;
};
template<class ...TT>
float get(const Map<std::string,TT> &...mm,const std::string &k,float defaultVal) {
return (std::nullopt | ... | Search(mm,k)).value_or(defaultVal);
}

最新更新