其他分享
首页 > 其他分享> > c – std :: unordered_map :: find使用与Key类型不同的类型?

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:

Live Coliru Demo

#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