首先,正如理查德霍奇斯在他的回答中所说,您不能使用 std::weak_ptr 作为密钥,因为它不稳定。忽略这一点,我们可以看看一般问题:我们可以使用 lambdas 作为模板参数吗?
通用解决方案是按照the following answer 中的说明进行操作。有两点需要注意
- 必须单独定义 lambda。
- lambda 必须作为参数传入。
2) 的原因是默认构造函数从编译器为 lambda 创建的类型中移除。
对于std::set,这还不错,但考虑std::unordered_map,它没有采用单个键比较函数的构造函数:
auto compare = [](const A & lhs, const A & rhs) { return lhs==rhs; };
std::unordered_map<
A,
B,
std::hash<A>,
decltype(compare)
> map1{0, std::hash<A>{}, compare};
第一个参数是初始桶大小,由实现定义。我使用 0 假设在插入第一项时实现将找到优化值。第二个是哈希函数,最后是 lambda。
我们可以通过将decltype(...) 替换为function<bool(A,A)> 来稍微改进它。这允许我们在头文件中声明类型,从而将其传递给其他函数,而无需共享实际的 lambda。声明将变为:
typedef std::unordered_map<
A,
B,
std::hash<A>,
std::function<bool(A,A)>
> custom_unordered_map;
而且可以这样使用:
custom_unordered_map map2{0, std::hash<A>{},
[](const A & lhs, const A & rhs) { return lhs==rhs; } };
此解决方案将允许直接使用自定义 lambda,也可以使用免费函数。
此解决方案的主要好处是它允许使用不同的比较函数,但使用起来非常冗长。
如果只需要一个比较函数,一个不太冗长的解决方案(对于该类型的用户)是定义一个仿函数:
struct Compare {
bool operator () (const A & lhs, const A & rhs) {
return lhs==rhs;
}
};
这可以正常使用:
std::unordered_map<A, B, std::hash<A>, Compare> map4;
注意:通过此解决方案,可以使用默认构造函数。
以下是一个完整的例子:
#include <functional>
#include <memory>
#include <unordered_map>
using A = int;
using B = int;
struct Compare {
bool operator () (const A & lhs, const A & rhs) {
return lhs==rhs;
}
};
bool compare_func(const A & lhs, const A & rhs) {
return lhs==rhs;
}
int main() {
// Using lamda: default constructor is deleted, so the lambda
// must be passed as argument to the constructor.
auto compare = [](const A & lhs, const A & rhs) { return lhs==rhs; };
std::unordered_map<
A,
B,
std::hash<A>,
decltype(compare)
> map1{0, std::hash<A>{}, compare};
// Alternative: use std::function. More general, and allows any lambda to be used
typedef std::unordered_map<
A,
B,
std::hash<A>,
std::function<bool(A,A)>
> custom_unordered_map;
custom_unordered_map map2{0, std::hash<A>{},
[](const A & lhs, const A & rhs) { return lhs==rhs; } };
custom_unordered_map map3{0, std::hash<A>{}, compare_func};
// Use of function class
std::unordered_map<A, B, std::hash<A>, Compare> map4;
}
这可以在 Ubuntu 15.10 上使用命令g++ map_lambda.cpp --std=c++11 -o map_lambda 编译。
我个人的意见是使用最后一种方案,除非需要使用不同的函数进行key比较。