使用string_view进行地图查找

Use of string_view for map lookup

本文关键字:地图 查找 view string 使用      更新时间:2023-10-16

以下代码无法在最近的编译器(g++-5.3,clang++-3.7)上构建。

#include <map>
#include <functional>
#include <experimental/string_view>
void f()
{
    using namespace std;
    using namespace std::experimental;
    map<string, int> m;
    string s = "foo";
    string_view sv(s);
    m.find(sv);
}

叮当返回的错误:

error: no matching member function for call to 'find'
    m.find(sv);
    ~~^~~~

但是find不应该能够使用类似的类型吗?Cpp首选项提到了以下重载:

template< class K > iterator find( const K& x );

boost::string_ref .

您需要显式指定透明比较器(如std::less<>):

std::map<std::string, int, std::less<>> m;
//                         ~~~~~~~~~~^

std::map<K,V>默认其比较器为std::less<K>(即非透明比较器),并且自([associaciative.reqmts]/p13)以来:

成员函数模板findcountlower_boundupper_boundequal_range不应参与重载解析,除非限定 id Compare::is_transparent有效并表示类型 (14.8.2)。

模板成员函数find不是可行的候选项。

关联容器的异构比较查找已添加到 c++14 中。最初的提案冒着破坏现有代码的风险。例如:

c.find(x);

在语义上等效于:

key_type key = x;
c.find(key);

特别是,xkey_type 之间的转换只发生一次,并且在实际调用之前

异构查找取代了这种转换,有利于keyx之间的比较。这可能会导致现有代码的性能下降(由于每次比较前的额外转换)甚至中断编译(如果比较运算符是成员函数,则不会对左侧操作数应用转换):

#include <set>
#include <functional>
struct A
{
    int i;
    A(int i) : i(i) {}
};
bool operator<(const A& lhs, const A& rhs)
{
    return lhs.i < rhs.i;
}
int main()
{
    std::set<A, std::less<>> s{{1}, {2}, {3}, {4}};
    s.find(5);
}

演示

为了解决这个问题,通过添加链接问题中所述的透明比较器的概念,使新行为选择加入。