如何将双参数Lambda传入std::remove_if删除Map中的元素?
问题:如何在std::remove_if中传递Date参数给双参谓词?
我有如下预定义Lambda函数:
auto condition = ParseCondition(is); auto predicate = [condition](const Date& date, const string& event) { return condition->Evaluate(date, event); };
该函数的作用:
- 接收字符串流输入并解析为condition;
- Lambda函数利用该condition与date、event进行比较,根据特定条件返回true/false。
我希望编写一个函数,利用上述predicate删除map对象中的元素。我的map对象定义为:map <Date,std::vector<std::string>> db;
我尝试了以下实现:
for(auto &item : db){ auto& date = item.first; auto& events = item.second; auto to_remove = std::remove_if(events.begin(),events.end(), predicate); events.erase(to_remove,events.end()); }
但问题在于predicate需要接收Date和event两个参数,我不知道如何将Date传入std::remove_if中,请问该如何解决?
解决方案
方法1:循环内包装成单参数Lambda(最直观)
std::remove_if要求谓词只能接受一个参数——也就是容器里的元素,这里是std::string类型的event。你可以在遍历map的循环里,捕获当前的date,把原来的双参predicate包装成单参Lambda传给remove_if:
for(auto &item : db){ auto& date = item.first; auto& events = item.second; // 捕获当前date,将原双参谓词包装为单参函数 auto to_remove = std::remove_if(events.begin(), events.end(), [&predicate, &date](const std::string& event) { return predicate(date, event); }); events.erase(to_remove, events.end()); }
方法2:用std::bind绑定Date参数
也可以用std::bind把date绑定到原predicate的第一个参数上,生成一个只需要event的单参函数对象:
#include <functional> // 需引入头文件 // ... for(auto &item : db){ auto& date = item.first; auto& events = item.second; // 绑定date为第一个参数,用占位符_1接收event参数 auto bound_pred = std::bind(predicate, std::cref(date), std::placeholders::_1); auto to_remove = std::remove_if(events.begin(), events.end(), bound_pred); events.erase(to_remove, events.end()); }
这里用std::cref是为了避免拷贝Date,保持引用传递,和原predicate的参数类型一致。
方法3:调整原predicate的定义(如果允许修改)
如果可以修改原predicate的创建逻辑,也可以让它生成一个需要捕获date的Lambda,不过这种方式灵活性稍差:
// 重新定义为返回单参Lambda的函数 auto make_predicate = [condition](const Date& date) { return [condition, date](const std::string& event) { return condition->Evaluate(date, event); }; }; // 循环中使用: for(auto &item : db){ auto& date = item.first; auto& events = item.second; auto to_remove = std::remove_if(events.begin(), events.end(), make_predicate(date)); events.erase(to_remove, events.end()); }
内容的提问来源于stack exchange,提问作者Daniil Yefimov
相关产品推荐
相关产品推荐

