我正在创建一个HandleManager
,其目的是简单地将Handle
s(typedef
long long int
}映射到string
。目的是使用Handle
的对象也可以通过string
标识,如果它有助于用户记住该对象。在这种情况下,在这张地图中:
typedef std::unordered_map<Handle, std::string> HandleMap;
该对中的两种类型都是键,只要它们可用于识别任何东西。到目前为止,除了需要获取Handle
的代码之外,所有内容都已编译完成。目的是当用户像这样分配string
时:
handle("myHandle");
随机生成Handle
,然后传递的string
在前面的地图中与之配对。我现在想要的是能够根据传递的Handle
获得与string
配对的string
:
Handle HandleManager::id(const std::string &name)
{
HandleMap::iterator it = pHandles.find(name);
if (it != pHandles.end())
return it->first;
return -1;
}
但是由于一些奇怪的原因,编译器抱怨这个:
HandleManager.cpp:48:45: error: no matching function for call to ‘std::unordered_map<long long int, std::basic_string<char> >::find(const string&)’
在上述地图中,string
是值,Handle
是关键。那么如何根据其中包含的值从unordered_map
获取键?
答案 0 :(得分:6)
std::unordered_map::find
按键操作,而不是值。您可以使用std::find_if
:
Handle HandleManager::id(const std::string &name)
{
auto it = std::find_if(std::begin(pHandles), std::end(pHandles),
[](auto&& p) { return p->second == name; });
if (it == std::end(pHandles))
return -1;
return it->first
}
请注意,auto
,std::begin
,std::end
和lambdas是C ++ 11,而通用lambdas是C ++ 14,所以如果你被困在那里,请用它们代替一个旧的编译器。
答案 1 :(得分:5)
您可以使用成员函数find
仅搜索密钥。要搜索值,可以使用带有lambda函数的std::find_if
(如果使用C ++ 11),或者遍历地图(在以前的C ++版本中可以):
for (HandleMap::const_iterator it = map.begin(); it != map.end(); ++it) {
if (it->second == name) return it->first;
}
// or value not found
另一方面,如果搜索值是一项非常常见的操作,您可能需要有两张地图:std::unordered_map<Handle, std::string>
和std::unordered_map<std::string, Handle>
。在这种情况下,您必须确保在两个地图中执行插入,删除等操作以保持同步。
答案 2 :(得分:2)
但是由于一些奇怪的原因,编译器抱怨这个:
当然可以,find
函数用于按键查找,而您却没有这样做。
要查找值,您需要访问每个元素,直到找到它(或使用将值映射回键的双向映射,例如Boost.Bimap)。
答案 3 :(得分:0)
基于answer from @TartanLlama(*):
Handle HandleManager::id(const std::string & name) {
auto iter = std::find_if(std::begin(pHandles), std::end(pHandles),
[& name](auto && pair) {
return pair.second == name;
});
if (it == std::end(pHandles)) {
return -1;
}
return it->first;
}
(*):因为似乎无法格式化注释中的代码。