如何推导for_each的模板参数funct?及用for_each删除unordered_map指定键
解决unordered_map批量删除与for_each的funct参数推导问题
首先先修正你代码里的小疏漏:std::vector keys_to_delete 需要明确元素类型,应该写成 std::vector<int> keys_to_delete = {0, 2};,否则编译器无法推导vector的模板参数。
一、for_each的funct模板参数推导逻辑
std::for_each 的核心函数签名大致是这样的:
template <class InputIt, class UnaryFunction> UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
你问的 funct 就是这里的 UnaryFunction 模板参数,它代表一个能接受单个参数(迭代器指向的元素类型)的可调用对象,常见的形式包括:
- 普通全局/成员函数
- lambda表达式
- 重载了
operator()的自定义函数对象 std::bind生成的绑定表达式
编译器会自动完成这个模板参数的推导:它会根据你传入的第三个参数的实际类型,直接确定UnaryFunction的具体实例化类型,完全不需要你手动指定——比如你传一个lambda,编译器就把这个lambda的匿名类型作为UnaryFunction的类型。
二、用for_each批量删除unordered_map元素的实现
要实现遍历keys_to_delete并删除sample_map中对应键的元素,最简洁直观的方式是用lambda表达式作为for_each的第三个参数,因为lambda可以方便地捕获外部的sample_map:
完整可运行代码
#include <unordered_map> #include <vector> #include <algorithm> #include <iostream> // 用于验证删除结果 int main() { std::unordered_map<int, bool> sample_map = { {0, false}, {1, true}, {2,false} }; std::vector<int> keys_to_delete = { 0, 2}; // 使用lambda作为for_each的可调用对象 std::for_each(keys_to_delete.begin(), keys_to_delete.end(), [&sample_map](int key) { sample_map.erase(key); // 通过键直接删除map中的元素 }); // 验证删除结果:此时map中应该只剩{1, true} for (const auto& pair : sample_map) { std::cout << pair.first << ": " << std::boolalpha << pair.second << std::endl; } }
为什么这样可行?
- lambda表达式
[&sample_map](int key) { sample_map.erase(key); }通过引用捕获了外部的sample_map(避免不必要的拷贝),并且接受一个int类型的参数(对应vector中的键),完全符合for_each对可调用对象的要求。 - 编译器自动推导
std::for_each的UnaryFunction模板参数为这个lambda的匿名类型,不需要你手动干预。 unordered_map::erase(key)是安全的:通过键删除元素时,不会触发迭代器失效问题(因为我们遍历的是独立的vector,不是map本身),即使键不存在,erase也只会静默忽略,不会抛出异常。
其他可选实现方式(用std::bind)
如果你偏好使用std::bind,也可以这样写(不过lambda的可读性更高):
#include <functional> // 需要包含这个头文件 // ... 其他代码不变 std::for_each(keys_to_delete.begin(), keys_to_delete.end(), std::bind(&std::unordered_map<int, bool>::erase, &sample_map, std::placeholders::_1));
这里std::bind把sample_map.erase成员函数绑定到sample_map的地址上,std::placeholders::_1代表后续传入的vector元素(即键),编译器同样会自动推导UnaryFunction为std::bind生成的绑定类型。
内容的提问来源于stack exchange,提问作者ajoseps
相关产品推荐
相关产品推荐

