gpt4 book ai didi

c++ - std::unordered_map - 使用 Lambda 专门化 KeyEqual

转载 作者:行者123 更新时间:2023-11-30 01:11:09 24 4
gpt4 key购买 nike

我想知道是否可以像这样创建 std::unordered_map 类型的变量:

std::unordered_map<std::weak_ptr<A>, B, std::hash<std::weak_ptr<A>,
[](const std::weak_ptr<A>& lhs, const std::weak_ptr<B>& rhs) -> bool { return lhs.lock() == rhs.lock(); }>

我希望它能工作,因为 KeyEqual 模板只需要一个实现 () 运算符的类型,但 visual studio 不允许我编译它,说它缺少 lambda 所在的类型。

最佳答案

首先,正如 Richard Hodges 在他的回答中所说,您不能使用 std::weak_ptr作为 key ,因为它不稳定。忽略这一点,然后我们可以看看一般性问题:我们可以将 lambda 用于模板参数吗。

通用解决方案是按照 the following answer 中的描述进行操作.有两点需要注意

  1. lambda 必须单独定义。
  2. 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)> .这允许我们在 header 中声明类型,因此无需共享实际的 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比较。

关于c++ - std::unordered_map - 使用 Lambda 专门化 KeyEqual,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36386366/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com