使用string_view进行地图查找

时间:2016-02-20 16:20:33

标签: c++ dictionary c++14 string-view

以下代码无法在最近的编译器上构建(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 个答案:

答案 0 :(得分:31)

您需要明确指定transparent comparator(例如std::less<>):

find

count将其比较器默认为std::less<K>(即非透明),并且([associative.reqmts]/p13):

  

成员函数模板lower_boundupper_boundequal_rangeCompare::is_transparentfind不得参与重载解析,除非符合条件 - id c.find(x); 有效且表示类型(14.8.2)。

模板成员函数key_type key = x; c.find(key); 不是一个可行的候选者。

Heterogeneous comparison lookup for associative containers已添加到。最初的提案有可能破坏现有代码。例如:

x

在语义上等同于:

key_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); } class Animal { var name:String init(name:String) { self.name = name } func speak() { } } class Cat: Animal { override init(name: String) { super.init(name: name) } override func speak() { println("Meow") } } 之间的比较。这可能会导致现有代码中的性能下降(由于每次比较之前的附加转换)或甚至中断编译(如果比较运算符是成员函数,则不会对左侧操作数应用转换):

class Animal
    {
        var name:String

        init(name:String)
        {
            self.name = name
        }

        func speak() { }
    }

    class Cat: Animal
    {
        var type: String = "Maine Coons"
        convenience init(type:string, name: String)
        {
            self.type = type
            self.init(name: name)
        }

        override func speak() {
            println("Meow")
        }
    }

DEMO

为了解决这个问题,我们通过添加linked question中描述的透明比较器概念来选择加入新行为。