首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >std::unordered_map::find是否使用了与密钥类型不同的类型?

std::unordered_map::find是否使用了与密钥类型不同的类型?
EN

Stack Overflow用户
提问于 2016-01-05 01:42:12
回答 5查看 10.9K关注 0票数 38

我有一个使用字符串类型作为键的unordered_map

代码语言:javascript
复制
std::unordered_map<string, value> map;

string提供了std::hash专门化,以及适当的operator==

现在我还有一个"string view“类,它是一个指向现有字符串的弱指针,避免了堆分配:

代码语言:javascript
复制
class string_view {
    string *data;
    size_t begin, len;
    // ...
};  

现在,我希望能够使用string_view对象检查映射中是否存在键。不幸的是,std::unordered_map::find接受Key参数,而不是一般的T参数。

(当然,我可以将一个“提升”为string,但这会导致我想要避免的分配。)

我想要的是像这样的东西

代码语言:javascript
复制
template<class Key, class Value>
class unordered_map
{
    template<class T> iterator find(const T &t);
};

这将需要适当地定义operator==(T, Key)std::hash<T>(),并将迭代器返回到匹配值。

有什么变通方法吗?

EN

回答 5

Stack Overflow用户

发布于 2020-09-28 19:17:27

我也面临着同样的问题。

我们需要两个结构:

代码语言:javascript
复制
struct string_equal {
    using is_transparent = std::true_type ;

    bool operator()(std::string_view l, std::string_view r) const noexcept
    {
        return l == r;
    }
};


struct string_hash {
    using is_transparent = std::true_type ;

    auto operator()(std::string_view str) const noexcept {
        return std::hash<std::string_view>()(str);
    }
};

对于unordered_map:

代码语言:javascript
复制
template <typename Value>
using string_unorderd_map = std::unordered_map<std::string, Value, string_hash, string_equal>;

对于unordered_set:

代码语言:javascript
复制
using string_unorderd_set = std::unordered_set<std::string, string_hash, string_equal>;

现在可以使用string_view了。

票数 4
EN

Stack Overflow用户

发布于 2016-01-05 07:50:52

这种解决方案有缺点,这可能会也可能不会使其在您的环境中可行。

您可以创建一个包装类:

代码语言:javascript
复制
struct str_wrapper {
  const char* start, end;
};

并将您的地图更改为使用str_wrapper作为其键。您必须向str_wrapper添加2个构造函数,一个用于std::string,另一个用于您的string_view。主要的决定是让这些构造函数执行深度复制还是浅复制。

例如,如果只将std::string用于插入,而将str_view仅用于查找,则可以将std::string构造函数设为深层,而将str_view构造函数设为浅(如果在unordered_map周围使用自定义包装器,则可以在编译时强制执行)。如果您希望避免在深度副本上发生内存泄漏,则需要额外的字段来支持适当的销毁。

如果您的用法更加多样化(查找std::string或通过str_view插入),将会有一些缺点,这可能会使这种方法过于令人反感,以至于不可行。这取决于您的预期用途。

票数 1
EN

Stack Overflow用户

发布于 2020-04-01 15:12:45

我只介绍我在github上找到的一个变体,它涉及到定义一个包装std的新映射类。

重新定义一些密钥API来拦截我们想要的适配器,并使用静态字符串来复制密钥。

这不一定是一个好的解决方案,但有趣的是,对于那些认为它足够好的人来说,它的存在是很有趣的。

原件:

https://gist.github.com/facontidavide/95f20c28df8ec91729f9d8ab01e7d2df

代码要点:

代码语言:javascript
复制
template <typename Value>
class StringMap: public std::unordered_map<std::string, Value>
{
public:
    typename std::unordered_map<string,Value>::iterator find(const nonstd::string_view& v )
    {
        tmp_.reserve(  v.size() );
        tmp_.assign( v.data(), v.size() );
        return std::unordered_map<string, Value>::find(tmp_);
    }

    typename std::unordered_map<std::string,Value>::iterator find(const std::string& v )
    {
        return std::unordered_map<std::string, Value>::find(v);
    }

    typename std::unordered_map<std::string,Value>::iterator find(const char* v )
    {
        tmp_.assign(v);
        return std::unordered_map<std::string, Value>::find(v);
    }

private:
    thread_local static std::string tmp_;
};

演职人员:

Davide Faconti

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34596768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档