以下代码无法在最近的编译器上构建(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
发生同样的错误。
答案 0 :(得分:31)
您需要明确指定transparent comparator(例如std::less<>
):
find
count
将其比较器默认为std::less<K>
(即非透明),并且([associative.reqmts]/p13):
成员函数模板
lower_bound
,upper_bound
,equal_range
,Compare::is_transparent
和find
不得参与重载解析,除非符合条件 - idc.find(x);
有效且表示类型(14.8.2)。
模板成员函数key_type key = x;
c.find(key);
不是一个可行的候选者。
Heterogeneous comparison lookup for associative containers已添加到c++14。最初的提案有可能破坏现有代码。例如:
x
在语义上等同于:
key_type
特别是key
和x
之间的转换仅发生一次,而发生在实际通话之前。
异构查找取代了此转化,有利于#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")
}
}
为了解决这个问题,我们通过添加linked question中描述的透明比较器概念来选择加入新行为。