c – std :: unordered_map :: find使用与Key类型不同的类型?
作者:互联网
我有一个使用字符串类型作为键的unordered_map:
std::unordered_map<string, value> map;
为字符串提供了std :: hash特化,以及a
合适的操作符==.
现在我还有一个“字符串视图”类,它是一个指向现有字符串的弱指针,避免了堆分配:
class string_view {
string *data;
size_t begin, len;
// ...
};
现在,我希望能够使用string_view对象检查地图中是否存在密钥.不幸的是,std :: unordered_map :: find采用Key参数,而不是泛型T参数.
(当然,我可以“提升”一个字符串,但这会导致我想避免的分配.)
我喜欢的是类似的东西
template<class Key, class Value>
class unordered_map
{
template<class T> iterator find(const T &t);
};
这将需要适当地定义operator ==(T,Key)和std :: hash< T>(),并将迭代器返回到匹配值.
有没有解决方法?
解决方法:
如上所述,C 14不为std :: unordered_map提供异构查找(与std :: map不同).您可以使用Boost.MultiIndex来定义std :: unordered_map的相当接近的替代,它允许您在不分配临时std :: strings的情况下查找string_views:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <string>
using namespace boost::multi_index;
struct string_view
{
std::string *data;
std::size_t begin,len;
};
template<typename T,typename Q>
struct mutable_pair
{
T first;
mutable Q second;
};
struct string_view_hash
{
std::size_t operator()(const string_view& v)const
{
return boost::hash_range(
v.data->begin()+v.begin,v.data->begin()+v.begin+v.len);
}
std::size_t operator()(const std::string& s)const
{
return boost::hash_range(s.begin(),s.end());
}
};
struct string_view_equal_to
{
std::size_t operator()(const std::string& s1,const std::string& s2)const
{
return s1==s2;
}
std::size_t operator()(const std::string& s1,const string_view& v2)const
{
return s1.size()==v2.len&&
std::equal(
s1.begin(),s1.end(),
v2.data->begin()+v2.begin);
}
std::size_t operator()(const string_view& v1,const std::string& s2)const
{
return v1.len==s2.size()&&
std::equal(
v1.data->begin()+v1.begin,v1.data->begin()+v1.begin+v1.len,
s2.begin());
}
};
template<typename Q>
using unordered_string_map=multi_index_container<
mutable_pair<std::string,Q>,
indexed_by<
hashed_unique<
member<
mutable_pair<std::string,Q>,
std::string,
&mutable_pair<std::string,Q>::first
>,
string_view_hash,
string_view_equal_to
>
>
>;
#include <iostream>
int main()
{
unordered_string_map<int> m={{"hello",0},{"boost",1},{"bye",2}};
std::string str="helloboost";
auto it=m.find(string_view{&str,5,5});
std::cout<<it->first<<","<<it->second<<"\n";
}
产量
boost,1
标签:unordered-map,c,c11 来源: https://codeday.me/bug/20190930/1835270.html