如果存在std::map<std::pair<std::string, std::string>, some_type>
找到其值的最佳方法是什么?
我想最明显的一个是做这样的事情:
但这将导致在对构造期间对和字符串map.find(std::make_pair(str1, str2));
进行复制构造。str1
str2
我希望也许map.find(std::make_pair(std::ref(str1), std::ref(str2)));
能有所帮助,但不幸的是没有,这仍然会产生字符串副本。
map.find(std::make_pair(std::move(str1), std::move(str2))
应该可以工作,但我们假设这些字符串 ( str1
, str2
) 是 const 或者不应该移动。
所以我问是否有其他方法可以进行地图搜索而不进行多余的字符串副本?
(请注意,使用std::string_view
forstd::map key
不是一个选项,因为地图应该拥有其字符串。)
C++14 添加了以下重载,
std::map::find
允许透明搜索:要利用它,您仍然需要
std::map
有一个合适的比较器:这
pair_less
是完全透明的。可以直接std::pair<X, Y>
比较std::pair<const X&, const Y&>
。注意事项
std::pair::operator<
自LWG Defect 3865以来, C++ 标准要求
std::pair::operator<
透明。理论上,这足以作为透明比较器。std::less<void>
std::ranges::less
std::pair
然而,在撰写本文时,libstdc++ 尚未实现透明比较std::less<void>
,因此仅适用于 GCC 以外的编译器。正确的 C++20 约束
适当地限制 的调用操作员
pair_less
并不那么容易。无论如何,这并不是绝对必要的,但会将错误移至操作员的调用站点,并且可能更适合诊断。通常的方法是这样的
也可以看看
boolean-testable
。为了避免密钥构造,您可以使用
std::map
透明比较器。在许多情况下,您不需要实现自己的标准 - 标准规定std::less<>
即可完成这项工作。不幸的是,它不适用于
std::pair
键,因为std::pair
缺乏异构比较:您无法std::pair<std::string, std::string>
与std::pair<const std::string&, const std::string&>
.但如果你可以更改
std::pair
为std::tuple
,它会起作用:即使您没有
std::string_view
密钥,您仍然可以用于std::string_view
比较器(因为您可以轻松转换std::string
->std::string_view
):std::tuple
使用而不是std::pair
因为您可以转换pair
->tuple
,但反之则不行。这意味着您也可以使用元组键,它具有方便的工厂功能:compare
使用两个而不是l < r
因为 C++20 之前的元组operator<
将导致三个memcmp
而不是两个(l[0] < r[0]; r[0] < l[0]; l[1] < r[1]
。这些似乎没有被优化)。