使用string_view进行map查找

75
以下代码在最新的编译器上无法构建(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);
}

clang返回的错误:

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

但是,find不应该能够使用可比类型吗?Cppreference提到了以下重载:

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

使用boost::string_ref也会出现相同的错误。

1个回答

91

您需要明确指定一个透明比较器(例如std::less<>):

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

std::map<K,V>默认使用std::less<K>(即非透明比较器),而且由于([associative.reqmts]/p13):

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

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

异类比较查找(Heterogeneous comparison lookup)被添加到中。原始提案存在破坏现有代码的风险。例如:

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);
}

演示

为了解决这个问题,我们添加了透明比较器的概念,并将其作为新的可选项,具体描述请参考相关问题


4
如何对 unordered_map 进行相同操作? - tuket
3
对于无序映射,建议使用C++20:https://dev59.com/41sW5IYBdhLWcg3wyJl3#53530846 - gluk47

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接