std::map<key_type, value_type>::find(different_key_type)
std::map<key_type, value_type>::find(different_key_type)
我有一个地图:
std::map<TyString, int> myMap;
然而,在某些情况下,我想通过比较TyString == TyStringRef
来std::map::find
一个条目,即
myMap.find(TyStringRef("MyString"));
原因是TyString包装了一个它自己分配和释放的const char *
。然而,为了只找到一个条目,我不喜欢分配一个新的字符串,相反,我只想使用引用(TyStringRef
只包装一个const char *
,而不分配或释放内存)。
当然,我可以将TyStringRef
转换为TyString
,但这样我就有了上面描述的内存开销。
有聪明的方法来解决这个问题吗?
谢谢!
注意,std::map::find
默认使用operator<
,或者一个用户定义的比较函函数。因此,除非您为TyString
和TyStringRef
重载operator<
,否则您无法在对数时间内查找键。由于operator==
被重载,您仍然可以在线性时间中查找,但不能使用std::map::find
。
为此,您应该使用#include <algorithm>
中的泛型算法,该算法独立于容器类。它可以接受任意类型T
,并使用operator==
与传入的迭代器operator*()
的结果进行比较。
std::find(sequence.begin(), sequence.end(), myKey);
然而,有一个问题:由于您有一个std::map
,它使用对作为迭代器,因此将比较键值对。因此,您必须使用std::find_if
,它接受谓词而不是值进行搜索。这个谓词应该返回您正在查找的元素的true
。您希望拥有first == myKey
所对应的元素(对),因此您最终得到如下代码:
std::find_if(myMap.begin(), myMap.end(), [](const std::pair<TyString,int> & pair) {
return pair.first == TyStringRef("MyString");
};
这在概念上是可行的,但它不会利用std::map
中的二叉树。因此,与std::map::find
的对数时间相比,将花费线性时间。
有一个替代方案,在开始时看起来有点奇怪,但它的优点是它将是一个对数时间查找。需要重载operator<(TyString,TyStringRef)
.您可以使用std::lower_bound
查找第一个元素,该元素不小于(大于或等于)给定的比较函数中的某个元素。
std::lower_bound(myMap.begin(), myMap.end(), TyStringRef("MyString"),
[](const std::pair<TyString,int> & entry, const & TyStringRef stringRef) {
return entry.first < stringRef;
}
);
在找到"下界"之后,您仍然需要测试键比较是否相等。如果没有,则表示没有找到该元素。因为有可能所有元素都与您正在查找的元素比较较少,所以返回的迭代器可能是end迭代器,不应该对其解引用。因此,完整的代码变成了这样,它类似于std::map::find
,如果没有找到键,则返回end迭代器:
template<class Map, class KeyCompareType,
class Iterator = typename Map::const_iterator>
Iterator findInMap(const Map &map, const KeyCompareType &key)
{
typedef typename Map::value_type value_type;
auto predicate = [](const value_type & entry, const KeyCompareType & key) {
return entry.first < key;
};
Iterator it = std::lower_bound(map.begin(), map.end(), key, predicate);
if (it != map.end()) {
if (!(it->first == key))
it = map.end();
}
return it;
}
生活例子
您可以使用STLport,它已经自己完成了这一点。也许其他标准库实现也这样做?或者,您也可以使用std::find(),但这会耗费您的对数查找。
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 在 QVector<std::unique_ptr 上使用 std::find<Type>>
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- 控制到达非空函数clang(-Wreturn-type)的末尾
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 将系数存储在头文件的数组中("does not name a type"错误)
- 尝试打开 ifstream 时出现"Incomplete type"错误
- 使用 Key 对 C++ 中的哈希映射进行排序. 无法排序
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在"结构提升::enable_if<提升::is_pod<T>,无效>"中没有名为"type"的类型
- "Missing type specifier - int assumed"无法通过向主函数添加"return 0"来解决
- OpenCV CV_16F type
- std::<key-value>不同类型的对向量
- C++ "错误:在'类 std::result_of< ... >"中没有名为'type'的类型"
- 将内存分配返回值强制转换为 TYPE 数组
- .value( "key" , default) 不适用于空的 json 对象吗?
- C++ 一个lambda浅拷贝const Type&如果它被赋予一个命名捕获,如[copy=val](){}?
- reference_wrapper导致"incomplete type is not allowed"